2011-10-05 10 views
2

IO :: Socket :: INETで同様のコードを使用する場合でも、クライアントが切断されると新しい接続を受け入れることに問題があります。Perlフォークソケットサーバー、クライアントの切断時に接続受け入れを停止します

以前のすべての子が終了/切断されるまで、親は新しい子をフォークするのをやめます。しかし、接続は受け入れられます。

誰かが私が間違っているアイデアを持っていますか?あなたはwaitpid戻り-1まで待っているので、すべての子どもたちが、終了したまでそれは意志ループ -

#!/usr/bin/perl -w 
use Socket; 
use POSIX qw(:sys_wait_h); 

sub REAPER { 
    1 until (-1 == waitpid(-1, WNOHANG)); 
    $SIG{CHLD} = \&REAPER; 
} 

$SIG{CHLD} = \&REAPER; 

$server_port=1977; 

socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); 
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1); 
$my_addr = sockaddr_in($server_port, INADDR_ANY); 
bind(SERVER, $my_addr) 
    or die "Couldn't bind to port $server_port : $!\n"; 
listen(SERVER, SOMAXCONN) 
    or die "Couldn't listen on port $server_port : $!\n"; 
print("[$$] STARTED\n"); 
while (accept(CLIENT, SERVER)) 
{ 
    next if $pid = fork; 
     die "fork: $!" unless defined $pid; 
    close(SERVER); 
    print("[$$] CONNECTED\n"); 
    while(<CLIENT>) 
    { 
     print("[$$] $_\n"); 
    } 
    print("[$$] EXIT\n"); 
    exit; 
} 
continue 
{ 
    close(CLIENT); 
} 
print("[$$] ENDED\n"); 

答えて

3

をPOSIX.1-2001準拠したシステムでは、単に$SIG{CHLD} = 'IGNORE'べきsolve the problemを設定します。

+0

これは最小のコードでトリックを行うようです!ありがとうございました。 –

1

私はあなたの問題がREAPERであると思います。

あなたはおそらく代わりにしたい:

my $kid; 
do { 
    $kid = waitpid(-1, WNOHANG); 
} while $kid > 0; 

参照: http://perldoc.perl.org/functions/waitpid.html

+0

' waitpid':

は、ここで全体のことです。 – mob

1

問題はacceptがSIGCHLDによって中断されていることです。修正:

for (;;) { 
    if (!accept(CLIENT, SERVER)) { 
     next if $!{EINTR}; 
     die $!; 
    } 

    ...fork and stuff... 
} 
0

OKこれは3ヶ月後のことですが、私は同じ問題を抱えていますが、その例を見つけようとしています1.複数の同時接続が可能で、永続的です。クライアントは終了しました。

リーパー機能を変更して少し近代化しました。 `WNOHANG`は、子プロセスがまだアクティブである場合に0を返しますが、それらのどれもが享受する準備ができていないと

#!/usr/bin/perl -w 
use Socket; 
use POSIX qw(:sys_wait_h); 

sub reaper { 
    1 until (-1 == waitpid(-1, WNOHANG)); 
    return($SIG{CHLD}); 
} 

$SIG{CHLD} = reaper(); 

$server_port=1977; 

socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); 
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1); 
$my_addr = sockaddr_in($server_port, INADDR_ANY); 
bind(SERVER, $my_addr) 
    or die "Couldn't bind to port $server_port : $!\n"; 
listen(SERVER, SOMAXCONN) 
    or die "Couldn't listen on port $server_port : $!\n"; 
print("[$$] STARTED\n"); 
while (accept(CLIENT, SERVER)) 
{ 
    next if $pid = fork; 
     die "fork: $!" unless defined $pid; 
    close(SERVER); 
    print("[$$] CONNECTED\n"); 
    while(<CLIENT>) 
    { 
     print("[$$] $_\n"); 
    } 
    print("[$$] EXIT\n"); 
    exit; 
} 
continue 
{ 
    close(CLIENT); 
} 
print("[$$] ENDED\n"); 
関連する問題