Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
#!/usr/local/bin/perl -w
# $Id: echo-server-select.pl,v 1.2 2002/02/05 17:53:08 68user Exp $
use Socket; # Socket モジュールを使う
$port = 5000;
# ソケット生成
socket(CLIENT_WAITING, PF_INET, SOCK_STREAM, 0)
|| die "ソケットを生成できません。$!";
# ソケットオプション設定
setsockopt(CLIENT_WAITING, SOL_SOCKET, SO_REUSEADDR, 1)
|| die "setsockopt に失敗しました。$!";
# ソケットにアドレス(=名前)を割り付ける
bind(CLIENT_WAITING, pack_sockaddr_in($port, INADDR_ANY))
|| die "bind に失敗しました。$!";
# ポートを見張る
listen(CLIENT_WAITING, SOMAXCONN)
|| die "listen: $!";
print "ポート $port を見張ります。\n";
%data_sockets = (); # 現在有効なデータコネクション用のハッシュテーブル
$client_num = 0; # クライアントの通し番号
$rin = &set_bits(CLIENT_WAITING); # ビット列を生成
while (1){
$ret = select($rout=$rin, undef, undef, undef);
printf("\$ret=$ret \$rout=%s,\$rin=%s\n", &to_bin($rout), &to_bin($rin));
if ( vec($rout, fileno(CLIENT_WAITING), 1) ){ # 新たにクライアントがやってきた
# ソケット名は毎回違う名前にする
$new_socket = "CLIENT_$client_num";
$sockaddr = accept($new_socket, CLIENT_WAITING);
# ホスト名、IPアドレス、クライアントのポート番号を取得
($client_port, $client_iaddr) = unpack_sockaddr_in($sockaddr);
$client_hostname = gethostbyaddr($client_iaddr, AF_INET);
$client_ip = inet_ntoa($client_iaddr);
print "接続: $client_hostname ($client_ip) ポート $client_port\n";
print "ソケット $new_socket を生成します。\n";
# クライアントに対してバッファリングしない
select($new_socket); $|=1; select(STDOUT);
# 接続中のクライアントをテーブルに登録
$data_sockets{$new_socket} = 1;
# select に渡すビット列を更新
$rin = &set_bits(CLIENT_WAITING, keys %data_sockets);
$client_num++;
} elsif ( $ret ){ # 接続中のクライアントから、データが送信されてきた
foreach $sock ( sort keys %data_sockets ){ # どのクライアントかを一つずつ確かめる
print " check... $sock\n";
if ( vec($rout, fileno($sock), 1) ){
if ( $in = <$sock> ){ # 1行読んでそのまま返す
print " $sock からの入力 .. $in";
print $sock "$in";
} else { # エラー発生=コネクション切断
print " コネクション切断 $sock\n";
close($sock); # ファイルハンドルを close
delete $data_sockets{$sock}; # テーブルから削除
# select に渡すビット列を更新
$rin = &set_bits(CLIENT_WAITING, keys %data_sockets);
}
}
}
}
}
#----------------------------------------------------
# 1個以上のファイルハンドルを受け取り、fileno で各ファイルハンドルの
# ディスクリプタ番号を調べ、それに対応するビットを立てたデータを返す。
# 例えば
# fileno(CLIENT_WAITING)==3
# fileno(CLIENT_1) ==4
# fileno(CLIENT_3) ==6
# のとき、
# &set_bits(CLIENT_WAITING, CLIENT_1, CLIENT_3)
# は
# 01011000
# というデータを返す。
sub set_bits {
@sockets = @_;
print "select に渡すビット列 \$rin を生成します。\n";
$rin="";
foreach $sock (@sockets){
# $rin の、右から数えて fileno($sock) 番目のビットを1にする。
vec($rin, fileno($sock), 1)=1;
printf(" fileno($sock) は %d なので \$rin は %s になります。\n",
fileno($sock),
&to_bin($rin),
);
}
return $rin;
}
#----------------------------------------------------
# 引数を受け取り、2進数の文字列(010111...)に変換して返す。
sub to_bin {
return unpack "B*", $_[0];
}