Вопрос о программировании сокетов Perl TCP - PullRequest
2 голосов
/ 27 декабря 2010

Приведенный ниже код запускает TCP-сервер, который создает новый процесс при получении 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;
}

Ответы [ 2 ]

3 голосов
/ 27 декабря 2010

Выход, потому что accept прерывается сигналом (SIGCHLD), и вы не обрабатываете этот случай. Попробуйте более сложную версию в perlipc: Интернет-клиенты и серверы TCP (прокрутите вниз до многопоточной версии).

Также рассмотрите возможность использования модуля, который обрабатывает эти детали для вас. 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 голосов
/ 27 декабря 2010

Я воспринимаю ваш вопрос как вопрос как код работает, а не спрашивает, почему он не работает.

Форки if ($pid = fork) создают дочерний процесс дляобработать запрос.В родительском элементе fork () возвращает pid дочернего элемента, поэтому родительский элемент закрывает дескриптор CLIENT и переходит к ожиданию следующего запроса для некоторого объекта in. Только в дочернем элементе, где fork () возвращает 0, код выходит за пределы блока if.выполняется, когда дочерний процесс обрабатывает запрос и затем завершает работу, поскольку родительский процесс будет иметь дело с ожиданием и обработкой следующего запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...