注: 如果你是知道Unix套接字,然后你可以跳过介绍部分。
另一个位计算机专业术语? 让我们看看网络的历史,这是一个伯克利分校UNIX的进程之间建立一个虚拟的全双工连接的机制。这后来被移植到所有已知的操作系统能够跨越地域位置上运行不同的操作系统,软件系统之间的通信。如果没有套接字,大多数的网络系统之间的通信将永远也不会发生的。
在仔细看看; 一个典型的计算机系统的网络上的接收和发送信息,运行在它之上的各种应用程序所必须的。 此信息被发送到系统中,由于一个唯一的IP地址被指定给它。在系统上,此信息提供给相关的应用程序在不同的端口上侦听。例如,一个网络浏览器监听80端口的信息。 同时,我们也可以编写应用程序在一个特定的端口号,收听和发送信息。
现在,让我们总结一下,一个套接字是IP地址和端口,它们可以连接。
为了说明的套接字,我们将使用客户端 - 服务器端编程的一个例子。为了完成一个客户端服务器架构,我们就得通过以下步骤
建立网络连接的第一个步骤是创建一个套接字,使用Socket()函数
socket( SOCKET, DOMAIN, TYPE, PROTOCOL ); creates a socket
套接字创建了一个SOCKET, 其他三个参数都是整数,它应该有以下值的TCP/IP连接。
因此,调用socket函数将是这样的:
use Socket #defines PF_INET and SOCK_STREAM socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);
bind( SOCKET, ADDRESS ) binds a network ADDRESS to a SOCKET.
ADDRESS 是一个套接字地址(TCP/ IP)数据包包含三个元素的字符串
正如bind()在服务器使用,并不需要知道它自己的地址,因此参数列表看起来像这样:
$port = 12345; # the port bind( SOCKET, pack( 'Sn4x8', AF_INET, $port, "\0\0\0\0" )) or die "Can't bind to port $port! \n";
or die 子句是非常重要的 -如果一台服务器死了,没有未完成的连接的端口不会立即可重复使用的,除非你使用这个选项SO_REUSEADDR使用setsockopt()函数。 这里pack()函数被用来打包所有数据成二进制格式。
如果这是一个服务器程序,那么它需要调用listen()监听在指定的端口。
listen( SOCKET, QUEUESIZE );
上面的调用是必须对所有服务器以及这里QUEUESIZE是连接请求允许的最大数量。一般情况下,listen()是用来在一个无限循环。只要一个连接到服务器处理并然后,立即去回到监听更多的连接。
如果这是一个服务器程序,那么它需要发出调用access()函数来接受传入的连接。
accept( NEW_SOCKET, SOCKET );
调用accept接收socket()函数返回的套接字描述符。成功完成此调用后,将返回一个新的socket描述符。今后所有客户端和服务器之间的通信发生的NEW_SOCKET和SOCKET是返回自己最擅长的 : listen()的一个新的连接。access() 调用失败,则返回FLASE我们最初使用的Socket模块中所定义的。
你会经常看到的accept()用于在一个while循环,如下所示
while(1) { accept( NEW_SOCKET, SOCKT ); ....... }
现在,所有与服务器的调用,让我们看到的调用将被客户端要求.
如果你要准备客户端程序,然后使用socket()调用后,你将不得不使用另一个调用connect()连接到服务器。
connect( SOCKET, ADDRESS );这里的地址是类似bind调用的远程服务器的IP地址,但它包含一个套接字地址。
$port = 21; # the ftp port $server_ip_address = "10.12.12.168"; connect( SOCKET, pack( 'Sn4x8', AF_INET, $port, $server )) or die "Can't connect to port $port! \n";
如果你连接到服务器成功后,你就可以开始你的命令发送到服务器使用SOCKET 描述符。
现在让我们把所有的东西放在一起
#!/usr/bin/perl -w # server.pl by www.gitbook.net #-------------------- use strict; use Socket; # use port 7890 as default my $port = shift || 7890; my $proto = getprotobyname('tcp'); # 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( 'Sn4x8', AF_INET, $port, "\0\0\0\0" )) 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(NET_SOCKET, SOCKET)) { # send them a message, close connection print NEW_SOCKET "Smile from the server"; close NEW_SOCKET; }
要运行该服务器在后台模式下发出Unix提示符下面的命令
$sever.pl&
#!/usr/bin/perl -w
# client.pl
#----------------
use strict;
use Socket;
# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "10.12.12.168";
# by www.gitbook.net
# 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( 'Sn4x8', AF_INET, $port, $server ))
or die "Can't connect to port $port! \n";
my $line;
while ($line = <SOCKET>) {
print "$line\n";
}
close SOCKET or die "close: $!";