2010-12-27 6 views
2

以下のコードは、TCPリクエストを受信したときに新しいプロセスをフォークするTCP Serverを実行します。最初のリクエストが受け入れられた直後に、なぜ終了するのですか?Perl TCP socket progammingに関する質問

 

#!/usr/bin/perl 

use Socket; 
use POSIX qw(:sys_wait_h); 

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

$SIG{CHLD} = \&REAPER; 
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); 
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1); 
$my_addr = sockaddr_in(8080, INADDR_ANY); 
bind SERVER, $my_addr; 
listen(SERVER, 1000); 
REQUEST: 
while (accept(CLIENT, SERVER)) { 
    if ($pid = fork) { 
    close CLIENT; 
    next REQUEST; 
    } 
    die "$!" unless defined $pid; 
    close SERVER; 
    print CLIENT "hello\n"; 
    close CLIENT; 
    exit; 
} 
 
+0

私は答えはわかりませんが、私がやるべき最初のことは、システムコールが何であるかを見るためにstraceの下で実行することです。 – araqnid

答えて

3

accept信号(SIGCHLD)によって中断され、あなたがそのケースを処理していないので、それは終了します。 perlipc: Internet TCP Clients and Serversでより洗練されたバージョンを試してください(マルチスレッド版までスクロールしてください)。

また、これらの詳細を処理するモジュールを使用することを検討してください。 Net::Server::Forkはあなたが書こうとしているようなものです。あなたがそれを気に入らなければ、他のモジュールもあります。

とにかく、ここにあなたのバージョンにはいくつかの最小限の修正です:

#!/usr/bin/perl 

use strict; 
use warnings; 
use Socket; 
use POSIX qw(:sys_wait_h); 

sub REAPER { 
    local $!;     # Don't let signal handler mess with $! 
    1 until -1 == waitpid(-1, WNOHANG); 
    $SIG{CHLD} = \&REAPER; 
} 

$SIG{CHLD} = \&REAPER; 
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); 
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1); 
my $my_addr = sockaddr_in(8080, INADDR_ANY); 
bind SERVER, $my_addr; 
listen(SERVER, 1000); 
REQUEST: 
while (1) { 
    my $paddr = accept(CLIENT, SERVER) || do { 
    # try again if accept() returned because a signal was received 
    next REQUEST if $!{EINTR}; 
    die "accept: $!"; 
    }; 

    my $pid; 
    if ($pid = fork) { 
    close CLIENT; 
    next REQUEST; 
    } 
    die "$!" unless defined $pid; 
    close SERVER; 
    print CLIENT "hello\n"; 
    close CLIENT; 
    exit; 
} 
0

私はコードがどのように動作するかそうでない理由を求めていない、を尋ねると、あなたの疑問を取っています。

if ($pid = fork) forksは、要求を処理するための子プロセスを作成します。親では、fork()は子のpidを返すので、親はCLIENTハンドルを閉じ、次の要求を待つために進む。fork()が0を返す子でのみifブロック親が次のリクエストを待って処理するので、子プロセスがリクエストを処理して終了する場所で実行されます。

+0

投稿したプログラムを実行してnetcatなどで接続しようとすると、最初の接続を処理した後にサーバが終了することがわかります。 – cjm