Perl - Socket编程

首页 / Perl入门教程 / Perl - Socket编程

Socket是在不同进程之间创建虚拟双工连接的Berkeley UNIX机制。后来将其移植到每个已知的OS上,以使跨不同OS软件运行的地理位置的系统之间进行通信。如果不使用Socket,系统之间的大多数网络通信将永远不会发生。

为了解释上面提到的Socket概念,我们将以使用Perl进行客户端-服务器编程为示例。要完成客户端服务器体系结构,我们必须执行以下步骤-

创建服务端

  • 使用 socket() 调用创建服务端Socket

  • 使用 bind 调用将Socket绑定到端口地址。

  • 使用 listen 调用在端口地址处监听Socket

  • 使用 accept 调用接受客户端连接。

创建客户端

  • 使用 socket() 调用创建Socket

  • 使用 connect 调用将(Socket)连接到服务器。

下图显示了客户端和服务器相互通信使用的完整呼叫顺序-

Perl Socket

服务端

socket() 函数

socket()调用是创建网络连接并创建Socket的第一个调用。该调用具有以下语法-

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

上面的调用创建了一个SOCKET,其他三个参数是整数,对于TCP/IP连接应具有以下值。

  • DOMAIN      -  应该是PF_INET。在您的计算机上大概是2。

  • TYPE            -  对于TCP/IP连接应为SOCK_STREAM。

  • PROTOCO    -  TCP之类的特定协议。

因此,服务器发出的Socket函数调用将如下所示:

use Socket     # This defines PF_INET and SOCK_STREAM

socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);

bind() 函数

服务器使用以下 bind函数来指定其将接受来自客户端的连接的端口。

bind( SOCKET, ADDRESS );

这里的SOCKET是socket()调用返回的描述符,而ADDRESS是包含三个元素的Socket地址(对于TCP/IP)

由于bind由服务器使用,服务器不需要知道其自己的地址,因此参数列表如下所示:

use Socket        # This defines PF_INET and SOCK_STREAM

$port=12345;    # The unique port used by the sever to listen requests
$server_ip_address="10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't bind to port $port!\n";

or die 子句非常重要,因为如果服务器在没有连接的情况下die,则除非使用 setsockopt函数使用选项SO_REUSEADDR,否则该端口将无法立即重用。在这里, pack_sockaddr_in函数用于将端口和IP地址打包为二进制格式。

listen() 函数

如果这是服务器程序,则需要在指定端口上发出对 listen的调用以进行监听,即等待传入的请求。该调用具有以下语法-

listen( SOCKET, QUEUESIZE );

上面的调用使用了socket()调用返回的SOCKET描述符,而QUEUESIZE是同时允许的最大未完成连接请求数。

accept() 函数

如果这是服务器程序,则需要发出对 access函数的调用以接受传入的连接。该调用具有以下语法-

accept( NEW_SOCKET, SOCKET );

接受调用接收由socket()函数返回的SOCKET描述符,成功完成后,将返回新的Socket描述符NEW_SOCKET,以用于客户端和服务器之间的所有将来通信。如果access调用失败,则它将返回FLASE,该FLASE在我们最初使用的Socket模块中定义。

通常,accept在无限循环中使用。一旦一个连接到达,服务器要么创建一个子进程来处理它,要么自己提供服务,然后返回以监听更多连接。

while(1) {
   accept( NEW_SOCKET, SOCKT );
   .......
}

现在,与服务器有关的所有呼叫均已结束,让我们看一看客户端需要的呼叫。

客户端

connect() 函数

如果要准备客户端程序,则首先将使用 socket()调用创建一个Socket,然后必须使用 connect调用进行连接服务器。您已经看过socket()调用语法,它将与服务器socket()()调用类似,但这是 connect()调用的语法-

connect( SOCKET, ADDRESS );

这里的SCOKET是由客户端发出的socket()调用返回的Socket描述符,而ADDRESS是类似于 bind 调用的Socket地址,除了它包含远程服务器的IP地址。

$port=21;    # For example, the ftp port
$server_ip_address="10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can't connect to port $port!\n";

如果成功连接到服务器,则可以开始使用SOCKET描述符将命令发送到服务器,否则客户端将通过显示错误消息来退出。

以下是使用PerlSocket实现简单的客户端-服务器程序的Perl代码。服务器在这里侦听传入的请求,并且一旦创建连接,它就简单地从服务器回复。客户端读取该消息并在屏幕上打印。假设我们在同一台计算机上拥有服务器和客户端,让我们看看它是如何完成的。

创建服务器脚本

#!/usr/bin/perl -w
# Filename : server.pl

use strict;
use Socket;

# use port 7890 as default
my $port=shift || 7890;
my $proto=getprotobyname('tcp');
my $server="localhost";  # Host IP running the server

# create a socket, make it reusable
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "Can't open socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "Can't set socket option to SO_REUSEADDR $!\n";

# bind to a port, then listen
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't bind to port $port!\n";

listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port\n";

# accepting a connection
my $client_addr;
while ($client_addr=accept(NEW_SOCKET, SOCKET)) {
   # send them a message, close connection
   my $name=gethostbyaddr($client_addr, AF_INET );
   print NEW_SOCKET "Smile from the server";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

要以后台模式运行服务器,请在Unix提示符下发出以下命令-

$perl sever.pl&

创建客户端脚本

!/usr/bin/perl -w
# Filename : client.pl

use strict;
use Socket;

# initialize host and port
my $host=shift || 'localhost';
my $port=shift || 7890;
my $server="localhost";  # Host IP running the server

# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "Can't create a socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can't connect to port $port!\n";

my $line;
while ($line=<SOCKET>) {
   print "$line\n";
}
close SOCKET or die "close: $!";

现在,让我们在命令提示符下启动客户端,该客户端将连接到服务器并读取服务器发送的消息,并在屏幕上显示如下内容:

$perl client.pl
Smile from the server

注意-如果您使用点号提供实际的IP地址,则建议在客户端和服务器中以相同格式提供IP地址,以免造成混淆。

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

人工智能基础课 -〔王天一〕

趣谈网络协议 -〔刘超〕

程序员的数学基础课 -〔黄申〕

从0开发一款iOS App -〔朱德权〕

TypeScript开发实战 -〔梁宵〕

现代C++编程实战 -〔吴咏炜〕

摄影入门课 -〔小麥〕

说透芯片 -〔邵巍〕

快手 · 音视频技术入门课 -〔刘歧〕

好记忆不如烂笔头。留下您的足迹吧 :)