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: }