Perlソケットプログラミング


ソケットは「ソケット」とも呼ばれます。アプリケーションは通常、「ソケット」を通じてネットワークにリクエストを送信したり、ネットワークリクエストに応答したりして、コンピューター上のホストまたはプロセスが通信できるようにします。

この章では、Perl 言語でソケット サービスを使用する方法を学びます。


サーバーを作成する

  • socket関数を使用してソケットサービスを作成します。

  • bind関数を使用してポートをバインドします。

  • ポートでリッスンするには、listen関数を使用します。

  • クライアントリクエストを受信するには、accept関数を使用します。

クライアントの作成

  • socket関数を使用してソケットサービスを作成します。

  • connect関数を使用してソケットサーバーに接続します。

次の図は、クライアントとサーバー間の通信プロセスを示しています:


サーバーソケット関数

ソケット関数

Perlでは、socket()関数を使用してソケットを作成します。形式は次のとおりです:

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

パラメータ分析:

  • DOMAIN 作成されたソケットはプロトコルセットを指定します。 例:


    • AF_INET は IPv4 ネットワーク プロトコルを意味します AF_INET 表示IPv4网络协议

    • AF_INET6 表示IPv6

    • AF_UNIX

    AF_INET6 は IPv6 を意味します
  • AF_UNIX は意味しますローカルソケット (ファイルを使用)

  • TYPE ソケットタイプは、接続指向か非接続かに応じて SOCK_STREAM または SOCK_DGRAM に分類できます

PROTOCOL

(getprotobyname) である必要があります('tcp' ))[2]

。使用される実際のトランスポート プロトコルを指定します。

したがって、ソケット関数呼び出しは次のようになります:
    use Socket     # 定义了 PF_INET 和 SOCK_STREAM
    
    socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2]);
  • bind() 関数

    は、bind() を使用してソケットにアドレスを割り当てます:
  • bind( SOCKET, ADDRESS );
  • SOCKET ソケットの記述子。 ADDRESS は、次の 3 つの要素を含むソケット アドレス (TCP/IP) です:

  • アドレス クラスター (TCP/IP、AF_INET、システムでは 2 である可能性があります)

ポート番号 (例: 21)

ネットワーク アドレス (10.12.12.168 など)

socket() を使用してソケットを作成した後は、使用されるプロトコルのみがソケットに与えられ、アドレスは割り当てられません。他のホストからの接続を受け入れる前に、bind() を呼び出してソケットにアドレスを割り当てる必要があります。

簡単な例は次のとおりです:

use Socket        # 定义了 PF_INET 和 SOCK_STREAM

$port = 12345;    # 监听的端口
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "无法绑定端口! \n";
or die

アドレスのバインドに失敗した後に実行されます。

setsockopt() オプション SO_REUSEADDR を設定して、ポートを即時再利用できるように設定します。

🎜pack_sockaddr_in()🎜関数はアドレスをバイナリ形式に変換します。 🎜🎜listen() 関数🎜🎜 ソケットがアドレスにバインドされると、listen() 関数は可能な接続リクエストのリッスンを開始します。ただし、これは信頼性の高いデータ フローが保証されている場合にのみ使用できます: 🎜
listen( SOCKET, QUEUESIZE );

SOCKET: ソケット記述子。

QUEUESIZE: 接続リクエストが到着すると、リスニング キューに入ります。接続リクエストが accept() によって受け入れられると、リスニング キューから削除されます。キューがいっぱいになると、新しい接続リクエストはエラーを返します。

接続が受け入れられると、成功の場合は 0 を返し、エラーの場合は -1 を返します。

accept() 関数

accept() 関数は、要求されたソケット接続を受け入れます。成功した場合はネットワーク アドレスの圧縮形式を返し、それ以外の場合は FALSE を返します:

accept( NEW_SOCKET, SOCKET );

SOCKET: ソケット記述子。

ADDRESS: ADDRESS はソケット アドレス (TCP/IP) であり、次の 3 つの要素が含まれます:

  • アドレス クラスター (TCP/IP、AF_INET、システムでは 2 である可能性があります)

  • ポート番号 (例: 21 )

  • ネットワーク アドレス (10.12.12.168 など)

accept() は通常、無限ループで使用されます:

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

上記の例では、クライアントのリクエストをリアルタイムで監視できます。


クライアント関数

connect() 関数

connect() システムコールは、ソケットの接続を設定します。パラメータはファイル記述子とホストアドレスです。

connect( SOCKET, ADDRESS );

以下は、サーバーソケットに接続されたインスタンスを作成します:

$port = 21;    #  ftp 端口
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
    or die "无法绑定端口! \n";

完全な例

次に、すべてのソケット関数のアプリケーションを理解するために完全な例を使用します:

サーバーserver.plコード:

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

use strict;
use Socket;

# 使用端口 7890 作为默认值
my $port = shift || 7890;
my $proto = getprotobyname('tcp');
my $server = "localhost";  # 设置本地地址

# 创建 socket, 端口可重复使用,创建多个连接
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "无法打开 socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "无法设置 SO_REUSEADDR $!\n";

# 绑定端口并监听
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "无法绑定端口 $port! \n";

listen(SOCKET, 5) or die "listen: $!";
print "访问启动:$port\n";

# 接收请求
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 "我是来自服务端的信息";
   print "Connection recieved from $name\n";
   close NEW_SOCKET;
}

ターミナルを開いて次のコードを実行します:

$ perl sever.pl
访问启动:7890

client.pl コード:

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

use strict;
use Socket;

# 初始化地址与端口
my $host = shift || 'localhost';
my $port = shift || 7890;
my $server = "localhost";  # 主机地址

# 创建 socket 并连接
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
   or die "无法创建 socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "无法连接:port $port! \n";

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

別のターミナルを開いて次のコードを実行します:

$ perl client.pl
我是来自服务端的信息