2010-12-27 4 views
2

아래 코드는 TCP 요청을 수신 할 때 새 프로세스를 포크하는 TCP 서버를 실행합니다. 첫 번째 요청을 수락 한 직후에 왜 종료됩니까? accept는 신호 (SIGCHLD)에 의해 중단됩니다하고 해당 사건을 처리하지 않기 때문에Perl TCP 소켓 프로그래밍에 대한 질문

 

#!/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

이 종료됩니다. 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) 포크, 즉 요청을 처리 할 하위 프로세스를 만듭니다. 부모에서 fork()는 자식의 pid를 반환하므로 부모는 CLIENT 핸들을 닫고 다음에있는 일부 요청을 기다립니다. fork()가 0을 반환하는 자식에서만 if 블록 이상으로 코드가 수행됩니다 부모는 다음 요청 대기 및 처리를 처리 할 것이기 때문에 요청이 처리 된 후 실행됩니다.

+0

게시 된 것처럼 프로그램을 실행하고 netcat 또는 다른 프로그램을 사용하여 연결하면 첫 번째 연결을 처리 한 후 서버가 종료된다는 것을 알 수 있습니다 (이유에 대한 대답 참조). – cjm