转:使用IO::Socket::INET模块实现socket编程

转自:http://blog.chinaunix.net/uid-26000296-id-3929863.html
In this article,let us discuss how to write Perl socket programming using theinbuilt socket modules in Perl.
Perlsocket modules provides an object interface that makes it easier tocreate and use TCP / UPD sockets.
本文讨论使用Perl内建的socket模块来实现Perlsocket编程

Thisarticle covers the following topics:
本文的主题如下:
.Perl example code for TCP client and server          (Perl实现TCP客户端和服务端)
.Perl example code for UDP client and server          (Perl实现UDP客户端和服务端)
.Read and write descriptor list using Select(IO::Select)(使用select来读写描述符列表)


CPANmodule IO::Socket::INET is used to perform socket operations suchas 
—creating, binding, connecting, listening and closing thesocket.
IO::Select moduleis used for obtaining the descriptors that are ready for read/writeoperations.
IO::Socket::INET用来执行socket操作,如创建,绑定,连接,监听,和关闭socket;
IO::Select模块用来获得可读/写操作的描述符;

PerlTCP Client and Server
TCP isa connection oriented networkingprotocol. 
In thisexample, let us review the Perl code-snippet that will explainingus the simple client and server communication.


PerlTCP Server Operation
PerlTCP 服务端操作
Thesocket operation such as socket creation, binding and listening tothe socket is performed by the IO::Socket::INETmodule.

ThePerl code given below does the following:
.Create the Socket                       (创建socket)
.Bind the socket to an address and port     (绑定socket的地址和端口)
.Listen to the socket at the port address   (监听端口)
.Accept the client connections             (接受连接)
.Perform read/write operation on the socket. (执行读写操作)


#!/usr/bin/perl
#tcpserver.pl

useIO::Socket::INET;

#flush after every write
$| =1;


my($socket,$client_socket);
my($peeraddress,$peerport);


#creating object interface of IO::Socket::INET modules whichinternally does
#socket creation, binding and listening at the specified portaddress.
$socket= new IO::Socket::INET (
   LocalHost => '127.0.0.1',
   LocalPort => '5000',
   Proto => 'tcp',
   Listen => 5,
   Reuse => 1
) ordie "ERROR in Socket Creation : $!\n”;


print"SERVER Waiting for client connection on port 5000";


while(1)
{
 # waiting for new client connection.
 $client_socket = $socket->accept();


 # get the host and port number of newly connectedclient.
 $peer_address = $client_socket->peerhost();
 $peer_port = $client_socket->peerport();


 print “Accepted New Client Connection From : $peeraddress,$peerport\n ”;


 # write operation on the newly accepted client.
 $data = “DATA from Server”;
 print $client_socket “$data\n”;


 # we can also send the data through IO::Socket::INETmodule,
 # $client_socket->send($data);


 # read operation on the newly accepted client
 $data = <$client_socket>;


 # we can also read from socket through recv()  inIO::Socket::INET
 # $client_socket->recv($data,1024);
 print “Received from Client : $data\n”;
}


$socket->close();


Also,refer to our earlier Perl debugger article to learn how to debugyour perl code.

PerlTCP Client Operation
PerlTCP 客户端操作
ThePerl code given below does the following:
.Create the socket.                           (创建socket) 
.Connect to the remote machine at a specific port. (连接服务端的端口)
.Perform read/write operation on the socket.      (执行读/写操作)


#!/usr/bin/perl
#tcpclient.pl


useIO::Socket::INET;


#flush after every write
$| =1;


my($socket,$client_socket);


#creating object interface of IO::Socket::INET modules whichinternally creates
#socket, binds and connects to the TCP server running on thespecific port.
$socket= new IO::Socket::INET (
   PeerHost => '127.0.0.1',
   PeerPort => '5000',
   Proto => 'tcp',
) ordie "ERROR in Socket Creation : $!\n”;


print“TCP Connection Success.\n”;


#read the socket data sent by server.
$data= <$socket>;


# wecan also read from socket through recv()  inIO::Socket::INET
#$socket->recv($data,1024);
print“Received from Server : $data\n”;


#write on the socket to server.
$data= “DATA from Client”;
print$socket “$data\n”; #发送数据给server


# wecan also send the data through IO::Socket::INETmodule,
#$socket->send($data);


sleep(10);
$socket->close();

Note: You can use Vim editor as a Perl IDE using theperl-support.vim Plugin.


PerlUDP Server
PerlUDP 服务端
ThePerl code given below does the following:
.Create the socket.                 (创建socket) 
.Bind the socket to the specific port. (绑定端口)


#!/usr/bin/perl
#udpserver.pl


useIO::Socket::INET;


#flush after every write
$| =1;


my($socket,$received_data);
my($peeraddress,$peerport);


we call IO::Socket::INET->new() to create theUDP Socket and bound
# tospecific port number mentioned in LocalPort and there is no need toprovide
#LocalAddr explicitly as in TCPServer.
$socket= new IO::Socket::INET (
   LocalPort => '5000',
   Proto => 'udp',
) ordie "ERROR in Socket Creation : $!\n”;


while(1)
{
 # read operation on the socket
 $socket->recv($recieved_data,1024);


 #get the peerhost and peerport at which the recent datareceived.
 $peer_address = $socket->peerhost();
 $peer_port = $socket->peerport();
 print "\n($peer_address , $peer_port) said :$recieved_data";


 #send the data to the client at which the read/write operationsdone recently.
 $data = “data from server\n”;
 print $socket “$data”;
}


$socket->close();


PerlUDP Client
PerlUDP 客户端
ThePerl code given below does the following:
.Create the UDP client.                     (创建socket) 
.Connect to the specific UDP server.           (连接到指定UDP服务端)
.Perform write and read operation on the socket.(执行读/写操作)


#!/usr/bin/perl
#udpclient.pl


useIO::Socket::INET;


#flush after every write
$| =1;


my($socket,$data);


# Wecall IO::Socket::INET->new() to create the UDPSocket
# andbind with the PeerAddr.
$socket= new IO::Socket::INET (
   PeerAddr   =>'127.0.0.1:5000',
   Proto       => 'udp'
) ordie "ERROR in Socket Creation : $!\n”;


#sendoperation
$data= “data from client”;
$socket->send($data);


#readoperation
$data= <$socket>;

print“Data received from socket : $data\n ”;


sleep(10);
$socket->close();


Also,refer to our earlier article to understand Perl ArrayReference.


IO::Select Module –Get to know the list of ready descriptors
IO::Select Module –获得准备好的描述符


IO::Selectmodule provides following two major functions:
.can_read() returns the available read descriptors  (返回可读的描述符) 
.can_write() returns the available write descriptors(返回可写的描述符)


Tounderstand the usage of IO::Select, we are going to use this modulein the tcpserver code.

Step 1: Create the IO::Socket object interface
创建IO::Socket对象接口

Thefollowing code-snippet creates the object interface ofIO::Socket::INET modules 
whichinternally creates a socket, binds and listens to a specified portaddress.

$socket= new IO::Socket::INET (
   LocalHost => '127.0.0.1',
   LocalPort => '5000',
   Proto => 'tcp',
   Listen => 5,
   Reuse => 1
) ordie "ERROR in Socket Creation : $!\n";

$select= IO::Select->new($socket) or die "IO::Select $!";


Step 2: Add descriptors to Select objects
将描述符添加到Select对象

Thefollowing code-snippet adds the descriptor to the list of selectobjects to get the descriptors ready.

@ready_clients= $select->can_read(0);
foreachmy $fh (@ready_clients)  {
 print $fh "";
 if($fh == $socket) {
   my $new = $socket->accept();
   $select->add($new);
 }
}

Step 3:Get descriptors which are ready to read
获得可读的描述符

Following Perlcode-snippets gets the list of descriptor that are ready toread.

@ready_clients= $select->can_read(0);
foreachmy $fh (@ready_clients)  {
 if($fh != $socket)  {
   chomp($data=<$socket>);
   print $data,"\n";
 }
}


In thesame way, we can do for the write operation on thesocket.

Step 4:Remove Client Socket Descriptor from Select list
将客户端socket描述符从select列表中删除

Whenthe connection is closed, you can remove the client socketdescriptor for the select list as shown below.
当连接关闭后,需要将socket描述符从select列表中删除


SIGPIPE signal getsgenerated when we try to send/receive data on the socket that isclosed by the remote machine. 
So, wecan assign the signal handler for SIGPIPE signal, which shouldremove of descriptor from the select list as shownbelow.
在使用socket进行数据的发送/接收中,当远端机器关闭socket连接时,将会发送SIGIPE信号.
因此,我们可以在收到SIGIPE信号时,将描述符从select列表中删除

#$current_client is the global variable which has the recent filedescriptor
# onwhich the send/receive operation is tried.
###Handle the PIPE
$SIG{PIPE}=  sub
{
 ####If we receieved SIGPIPE signal then call Disconnect this clientfunction
 print "Received SIGPIPE , removing a client..\n";
 unless(defined $current_client){
   print "No clients to remove!\n";
 }else{
  $Select->remove($current_client);
   $current_client->close;
 }


 #print Dumper $Self->Select->handles;
 print "Total connected clients=>".(($Select->count)-1)."<\n";
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值