Написание сервера TCP

Проблема

Вы хотите написать сервер, который ожидает подключения клиентов по сети к определенному порту.

Решение

Следующее решение предполагает, что связь осуществляется через Интернет. Воспользуйтесь стандартным (для версии 5.004) классом IO::Socket::INET:
use IO::Socket:
$server = IO::Socket::INET->new(LocalPort => $server_port,
                                Type      => SOCK_STREAM,
                                Reuse     => 1,
                                Listen    => 10 )  # or SOMAXCONN
  or die "Couldn't be a tcp server on port $server_port : $@\n";
while ($client = $server->accept()) {
  # $client  - новое подключение
}
close($server);
Или создайте сокет вручную, что позволит получить полный контроль над ним:
use Socket;
# Создать сокет
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";
# Принимать и обрабатывать подключения
while (accept(CLIENT, SERVER)) {
  # Сделать что-то с CLIENT
}
close(SERVER);

Комментарий

Написать сервер сложнее, чем клиент. Необязательная функция listen сообщает операционной системе, сколько подключений могут находиться в очереди к серверу, ожидая обслуживания. Функция setsockopt, использованная в решении, позволяет избежать двухминутного интервала после уничтожения сервера перед ею перезапуском (полезна при тестировании). Функция bind регистрирует сервер в ядре. Наконец, функция accept последовательно принимает входящие подключения.
Числовой аргумент listen определяет количество не принятых функцией accept подключений, которые будут поставлены в очередь операционной системой перед тем, как клиенты начнут получать ошибки «отказ в обслуживании». Исторически максимальное значение этого аргумента было равно 5, но и сегодня многие операционные системы тайно устанавливают максимальный размер очереди равным примерно 20. Сильно загруженные Web-серверы стали распространенным явлением, поэтому многие поставщики увеличивают это значение. Максимальный размер очереди для вашей системы хранится в константе SOMAXCONN модуля Socket.
Функции accept передаются два аргумента: файловый манипулятор, подключаемый к удаленному клиенту, и файловый манипулятор сервера. Она возвращает IP-адрес и порт клиента, упакованные inet_ntoa:
use Socket;
while ($client_address = accept(CLIENT, SERVER)) {
  ($port, $packed_ip) = sockaddr_in($client_address);
  $dotted_quad = inet_ntoa($packed_ip);
  # Обработать
}
В классах IO::Socket accept является методом, вызываемым для манипулятора сервера:
while (($client,$client_address) = $server->accept()) {
  # ...
}
Если ожидающих подключений нет, программа блокируется на вызове accept до того, как появится подключение. Если вы хотите гарантировать, что вызов accept не будет блокироваться, воспользуйтесь неблокирующими сокетами:
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
$flags = fcntl($SERVER, F_GETFL, 0)
  or die "Can't get flags for the socket: $!\n";
$flags = fcntl($SERVER, F_SETFL, $flags | O_NONBLOCK)
  or die "Can't set flags for the socket: $!\n";
Если теперь при вызове accept не окажется ожидающих подключений, accept вернет undef и присвоит $! значение EWOULDBLOCK.
Может показаться, что при возвращении нулевых флагов от F_GETFL будет вызвана функция die, как и при неудачном вызове, возвращающем undef. Это не так — неошибочное возвращаемое значение fcntl, как и для ioctl, преобразуется Perl в специальное значение "0 but true". Для этой специальной строки даже действуют надоедливые предупреждения флага -w о нечисловых величинах, поэтому вы можете использовать ее в своих функциях, когда возвращаемое значение равно 0 и тем не менее истинно.

См. также

Описание функций socket, bind, listen, accept, fcntl



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: