≡菜单

如何:使用IO :: Socket :: INET进行Perl TCP / UDP套接字编程

在本文中,让我们讨论如何使用Perl中的内置套接字模块编写Perl套接字编程。

Perl套接字模块提供了一个对象接口,使创建和使用TCP / UPD套接字更加容易。

本文涵盖以下主题:

  • TCP客户端和服务器的Perl示例代码
  • UDP客户端和服务器的Perl示例代码
  • 使用Select(IO :: Select)读取和写入描述符列表

CPAN模块IO :: Socket :: INET用于执行套接字操作,例如—创建,绑定,连接,监听和关闭套接字。

IO :: Select模块用于获取准备好进行读/写操作的描述符。

Perl TCP客户端和服务器

TCP是面向连接的网络协议。在此示例中,让我们回顾一下Perl代码片段,它将向我们解释简单的客户端和服务器通信。

Perl TCP服务器操作

套接字操作(例如套接字创建,绑定和侦听套接字)由IO :: Socket :: INET模块执行。

下面给出的Perl代码执行以下操作:

  • 创建套接字
  • 将套接字绑定到地址和端口
  • 在端口地址监听套接字
  • 接受客户端连接
  • 在套接字上执行读/写操作。
#!/usr/bin/perl
#tcpserver.pl

使用IO :: Socket :: INET;

#每次写入后刷新
$| = 1;

我的($ socket,$ client_socket);
我的($ peeraddress,$ peerport);

#创建内部执行的IO :: Socket :: INET模块的对象接口 
#在指定的端口地址上创建,绑定和侦听套接字。
$socket = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => '5000',
Proto => 'tcp',
Listen => 5,
Reuse => 1
) 或者死"创建套接字时出错:$!\ n”;

print "SERVER等待端口上的客户端连接5000";

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

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

打印“接受的新客户端连接来自:$ peeraddress,$ peerport \ n”;

# write operation 上  the newly accepted client.
$data = “DATA from Server”;
print $client_socket “$data\n”;
# we can also send the data through IO::Socket::INET module,
# $client_socket->send($data);

# read operation 上  the newly accepted client
$data = <$client_socket>;
# we can also read from socket through recv()  in IO::Socket::INET
# $client_socket->recv($data,1024);
print “Received from Client : $data\n”;
}

$socket->close();

另外,请参阅我们前面的 Perl调试器 文章,了解如何调试Perl代码。

Perl TCP客户端操作

下面给出的Perl代码执行以下操作:

  • 创建套接字。
  • 在特定端口连接到远程计算机。
  • 在套接字上执行读/写操作。
#!/usr/bin/perl
#tcpclient.pl

使用IO :: Socket :: INET;

#每次写入后刷新
$| = 1;

我的($ socket,$ client_socket);

# creating object interface of IO::Socket::INET modules which internally creates 
# socket, binds and connects to the TCP server running 上  the specific port.
$socket = new IO::Socket::INET (
PeerHost => '127.0.0.1',
PeerPort => '5000',
Proto => 'tcp',
) 或者死"创建套接字时出错:$!\ n”;

print “TCP Connection Success.\n”;

# read the socket data sent 通过 server.
$data = <$socket>;
# we can also read from socket through recv()  in IO::Socket::INET
# $ socket- >recv($data,1024);
print “Received from Server : $data\n”;

# write 上  the socket to server.
$data = “DATA from Client”;
print $socket “$data\n”;
# we can also send the data through IO::Socket::INET module,
# $ socket- >send($data);

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

注意:您可以使用 Vim编辑器作为Perl IDE 使用perl-support.vim插件。

Perl UDP服务器

下面给出的Perl代码执行以下操作:

  • 创建套接字。
  • 将套接字绑定到特定端口。
#!/usr/bin/perl
#udpserver.pl

使用IO :: Socket :: INET;

#每次写入后刷新
$| = 1;

我的($ socket,$ received_data);
我的($ peeraddress,$ peerport);

#  we call IO::Socket::INET->new() to create the UDP Socket and bound 
# to specific port number mentioned in LocalPort and there is no need to provide 
# LocalAddr explicitly as in TCPServer.
$socket = new IO::Socket::INET (
LocalPort => '5000',
Proto => 'udp',
) 或者死"创建套接字时出错:$!\ n”;

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

#get the peerhost and peerport at which the recent data received.
$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 operations done recently.
$data = “data from server\n”;
print $socket “$data”;

}

$socket->close();

Perl UDP客户端

下面给出的Perl代码执行以下操作:

  • 创建UDP客户端。
  • 连接到特定的UDP服务器。
  • 在套接字上执行写和读操作。
#!/usr/bin/perl
#udpclient.pl

使用IO :: Socket :: INET;

#每次写入后刷新
$| = 1;

my ($socket,$data);

#  We call IO::Socket::INET->new() to create the UDP Socket 
# and bind with the PeerAddr.
$socket = new IO::Socket::INET (
PeerAddr   => '127.0.0.1:5000',
Proto        => 'udp'
) 或者死"创建套接字时出错:$!\ n”;
#send operation
$data = “data from client”;
$socket->send($data);

#read operation
$data = <$socket>;
print “Data received from socket : $data\n ”;

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

另外,请参阅我们之前的文章以了解 Perl阵列参考.

IO :: Select模块–了解准备好的描述符列表

IO :: Select模块提供以下两个主要功能:

  • can_read()返回可用的读取描述符
  • can_write()返回可用的写描述符

要了解IO :: Select的用法,我们将在tcpserver代码中使用此模块。

步骤1:创建IO :: Socket对象接口

以下代码段创建了IO :: Socket :: INET模块的对象接口,该模块在内部创建一个套接字,绑定并侦听指定的端口地址。

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

$select = IO::Select->new($socket) 或者死"IO::Select $!";

步骤2:向选择对象添加描述符

下面的代码片段将描述符添加到选择对象列表中,以准备好描述符。

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

步骤3:获取准备读取的描述符

以下Perl代码片段获取了准备读取的描述符列表。

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

同样,我们可以对套接字执行写操作。

步骤4:从“选择”列表中删除“客户端套接字描述符”

关闭连接后,可以删除选择插槽的客户端套接字描述符,如下所示。

当我们尝试在远程计算机关闭的套接字上发送/接收数据时,会生成SIGPIPE信号。因此,我们可以为SIGPIPE信号分配信号处理程序,该信号处理程序应从选择列表中删除描述符,如下所示。

# $current_client is the global variable which has the recent file descriptor 
# 上  which the send/receive operation is tried.
### Handle the PIPE
$SIG{PIPE} =  sub
{
####If we receieved SIGPIPE signal then call Disconnect this client function
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";
};

如果您喜欢这篇文章,您可能还会喜欢..

  1. 50个Linux Sysadmin教程
  2. 50个最常用的Linux命令(包括示例)
  3. 排名前25位的最佳Linux性能监视和调试工具
  4. 妈妈,我找到了! – 15个实用的Linux Find命令示例
  5. Linux 101 Hacks第二版电子书 Linux 101黑客手册

Bash 101 Hacks书 Sed和Awk 101黑客手册 Nagios Core 3书 Vim 101黑客手册

{ 10 评论… 加一 }

  • 克拉 2010年7月2日,上午4:39

    代码有一些麻烦– the part with
    或者死“创建套接字时出错:$!\ n”;
    使用错误的引号(不匹配)

  • 克拉 2010年7月2日,上午4:40

    …您的解析器中的注释修复了我无与伦比的引号。 --

  • 詹姆士 2010年7月5日,下午5:07

    如何监视IO套接字?

    我的套接字不断向远程服务器发送查询(每毫秒)

    我需要知道套接字是否引起了问题(即丢弃数据包或缓冲)

    很棒的文章,请写更多-

    保持良好的工作状态!

  • 安德鲁 2010年9月15日,下午5:47

    请摆脱“smart”代码示例中的引号。

  • 维诺德·哈拉哈维(Vinod Halaharvi) 2011年3月22日,下午2:53

    #能够将服务器连接到多个端口以及每个端口上的多个客户端

    使用警告;
    使用IO :: Socket :: INET;
    使用IO :: Select;

    #每次写入后刷新
    $ | = 1;

    我的($ socket,$ client_socket);
    我的($ peeraddress,$ peerport);
    #创建内部执行的IO :: Socket :: INET模块的对象接口
    #在指定的端口地址上创建,绑定和侦听套接字。
    $ numArgs = $#ARGV + 1;

    #对于新服务器套接字的命令行上的每个端口,
    #每个端口一个服务器插槽
    foreach $ argnum(0 .. $#ARGV){
    我的($端口)= $ ARGV [$ argnum];

    #复制此程序
    my($ pid)= fork();
    如果($ pid!= 0){
    #父进程
    打印“parent\n”;
    打印“Done with parent..\n”;
    }
    其他{
    #子进程
    $ lsn =新的IO :: Socket :: INET(
    LocalHost => ‘127.0.0.1’,
    LocalPort => $port,
    原始=> ‘tcp’,
    听=> 1,
    重用=> 1
    );

    打印“Child\n”;
    my($ file_name)=“server.output”;
    打开我的$ log,‘>>’, $ file_name
    或者死“$ 0:打开输出文件失败‘$file_name’ : $!\n”;

    $ sel =新的IO :: Select($ lsn);
    打印“SERVER等待端口上的客户端连接“. $port. “\n”;
    而(@ready = $ sel->can_read) {
    foreach $ fh(@ready){
    if($ fh == $ lsn){
    #创建一个新的套接字
    my($ new)= $ lsn->accept;
    打印“Connect client: “. $new->sockaddr() . ” port: ” . $port . “\n”;
    $ sel->add($new);
    }
    其他{
    #进程套接字
    #也许我们已经完成了套接字
    my($ remote_address)= $ fh->recv($data,1024);
    打印$remote_address. “:” . $port .”:”. $data;
    }
    }
    } #while
    关闭($ log)
    或警告“$ 0:无法关闭输出文件‘$file_name’ : $!\n”;
    #return;
    $ socket- >close();
    }#其他
    } #for

  • 山姆 2011年8月26日,上午7:05

    您的服务器代码中有一个错字
    您分配两个变量
    $ peer_address = $ client_socket->peerhost();
    $ peer_port = $ client_socket->peerport();

    但是,然后使用错误的名称(对等地址/端口而不是对等地址/端口)
    打印“接受的新客户端连接来自:$ peeraddress,$ peerport \ n”;

    使用strict可能会发现这一点。

  • 皮特 2013年3月19日,上午4:20

    请注意拼写方式的差异。在udpserver.pl中

    该声明的拼写正确
    我的($ socket,$ received_data);
    使用不是’t
    $ socket- >recv($ recieved_data,1024);

    并不是说它阻止了一切,

  • 苏伦达M 2014年7月22日,上午12:59

    对我有用。该站点将简单而精妙地介绍perl中有关套接字的所有内容。

  • 奥立佛 2015年7月24日,上午9:38

    拉梅什·纳塔拉詹(Ramesh Natarajan),早上好,你好吗?我喜欢perl中的这个示例,我尝试调整上面的示例以从GPS接收数据,请参见我如何使用脚本:

    perl server.pl

    SERVER等待端口上的客户端连接5005

    已接受来自,的新客户端连接
    从客户收到:$ PGID,352346057056823 * 0b

    我问您是否可以帮助修改脚本以从GPS中获取数据。

  • 知识 2016年4月13日,上午8:36

    嘿,
    我有一个关于参数LENGTH = 1024的问题,该参数已用于:
    $ socket- >recv($data,1024);

    仅当有10K数据量时,函数recv返回?

发表评论