モジュールを使ってみよう (2)

前へ << モジュールを使ってみよう (1) モジュールを使ってみよう (3) >> 次へ

echo サーバ

IO::Socket モジュールを使った echo サーバです。

echo-server-io-socket.pl

    1: #!/usr/local/bin/perl
    2: 
    3: # $Id: echo-server-io-socket.pl,v 1.2 2002/02/05 17:53:08 68user Exp $
    4: 
    5: use IO::Socket;                   # IO::Socket モジュールを使う。
    6: 
    7: $port = 5000;                     # ポート番号を設定
    8: 
    9: $listening_socket = IO::Socket::INET->new(LocalPort => $port,
   10:                                           Listen    => SOMAXCONN,
   11:                                           Proto     => 'tcp',
   12:                                           Reuse     => 1,
   13:                                           );
   14: 
   15: if ( ! $listening_socket ){
   16:     die "listen できませんでした。 $!\n";
   17: }
   18: 
   19: print "ポート $port を見張ります。\n";
   20: 
   21: while (1){
   22:     $new_socket = $listening_socket->accept();
   23: 
   24:     $client_sockaddr = $new_socket->peername();
   25:     ($client_port,$client_iaddr) = unpack_sockaddr_in($client_sockaddr);
   26:     $client_hostname = gethostbyaddr($client_iaddr, AF_INET);
   27:     $client_ip = inet_ntoa($client_iaddr);
   28: 
   29:     print "接続: $client_hostname($client_ip) ポート $client_port\n";
   30: 
   31:     select($new_socket); $|=1; select(STDOUT);
   32: 
   33:     while (<$new_socket>){
   34:         print "メッセージ: $_";
   35:         print $new_socket $_;
   36:     }
   37:     $new_socket->close();
   38: 
   39:     print "接続が切れました。引き続きポート $port を見張ります。\n";
   40: }
socket、bind、setsockopt の分を短縮できています。
    9: $listening_socket = IO::Socket::INET->new(LocalPort => $port,
   10:                                           Listen    => SOMAXCONN,
   11:                                           Proto     => 'tcp',
   12:                                           Reuse     => 1,
   13:                                           );
クライアントの場合は引数に PeerAddr、PeerPort、Proto を 渡しましたが、サーバの場合は
  • LocalPort … ポート番号
  • Listen … 最大受け付けクライアント数。ここでは SOMAXCONN を指定。
  • Proto … プロトコル。ここでは tcp。
  • Reuse … 1 にすると、setsockopt(CLIENT_WAITING,SOL_SOCKET,SO_REUSEADDR,1) を 指定したのと同じ意味になる。
となります。クライアントとして動作するか、サーバとして動作するかは、 引数の内容で決まることに注意して下さい。 どちらも IO::Socket::INET->new を実行するという点では同じです。

マルチスレッド版

fork を使ったマルチスレッドサーバは以下のようになります。

echo-server-fork-io-socket.pl

    1: #!/usr/local/bin/perl
    2: 
    3: # $Id: echo-server-fork-io-socket.pl,v 1.2 2001/12/05 19:31:18 68user Exp $
    4: 
    5: use IO::Socket;                   # IO::Socket モジュールを使う。
    6: 
    7: $port = shift || 5000;            # ポート番号を設定
    8: 
    9: $listening_socket = IO::Socket::INET->new(LocalPort => $port,
   10:                                           Listen    => SOMAXCONN,
   11:                                           Proto     => 'tcp',
   12:                                           Reuse     => 1,
   13:                                           );
   14: 
   15: if ( ! $listening_socket ){
   16:     die "listen できませんでした。 $!\n";
   17: }
   18: 
   19: print "親プロセス($$): ポート $port を見張ります。\n";
   20: 
   21: while (1){
   22:     $new_socket = $listening_socket->accept();
   23: 
   24:     $client_sockaddr = $new_socket->peername();
   25:     ($client_port,$client_iaddr) = unpack_sockaddr_in($client_sockaddr);
   26:     $client_hostname = gethostbyaddr($client_iaddr,AF_INET);
   27:     $client_ip = inet_ntoa($client_iaddr);
   28: 
   29:     print "接続: $client_hostname($client_ip) ポート $client_port\n";
   30: 
   31:     if ( $pid = fork() ){           # 親プロセス
   32:         print "親プロセス($$): 引続きポート $port を見張ります。\n";
   33:         print "クライアントの相手は子プロセス $pid が行います。\n";
   34: 
   35:         $new_socket->close();
   36: 
   37:     } else {                 # 子プロセス
   38:         $listening_socket->close();
   39: 
   40:         select($new_socket); $|=1; select(STDOUT);
   41: 
   42:         while (<$new_socket>){
   43:             print "子プロセス($$): メッセージ $_";
   44:             print $new_socket $_;
   45:         }
   46:         $new_socket->close();
   47: 
   48:         print "子プロセス($$): 接続が切れました。終了します。\n";
   49:         exit;
   50:     }
   51: }
前へ << モジュールを使ってみよう (1) モジュールを使ってみよう (3) >> 次へ

ご意見・ご指摘は Twitter: @68user までお願いします。