A
AndyT
Пишу сокет сервер. При запуске сервера родитель Parent отщепляет процесс Worker. Сам Parent висит в блокирующем режиме и ловит подключения. Поймав клиента он передает его в Worker. Worker крутится в бесконечном цикле, каждую секунду опрашивая своих клиентов. Если от кого-то поступает сообщение, он тут же рассылает его всем остальным.
Проблема в том, что не могу передать от родителя манимупулятор клиента.
[codebox]#!/usr/bin/perl
# Server
#
use CGI;
use CGI::Carp qw (fatalsToBrowser);
use IO::Socket;
use IO::Select;
use Time::HiRes qw(sleep); # короткие задержки
use IO::Handle; # для pipe
my $q=new CGI;
$|=1; # запрет буферизации
print $q->header(-type => 'text/html', -charset => 'windows-1251');
$select = IO::Select->new();
$server_port=8888;
$server=IO::Socket::INET->new(
LocalPort => $server_port,
Type =>SOCK_STREAM,
Reuse =>1,
Listen => 10
);
pipe($reader,$writer); # открываем канал к потомку
$writer->autoflush(1);
if($child3=fork()){ # отщепляем потомка
# блок родителя
while($client=$server->accept()){
my ($ip,$port,$host)=who_is($client);
print $writer $client; # эта строка должна передавать манипулятор клиента в дочерний процесс Worker, но не передает.
#Обыкновенный скаляр, к примеру $Hello успешно передает.
# Worker НЕ ВИДИТ КЛИЕНТА
# В этом проблема!!!!!!!!!
$Hello="$ip:$port\n";
print $client "Parent $Hello"; # эта строка успешно возвращается клиенту
print "<p>Parent: $Hello ";
}
}else{
# Блок потомка Worker
while(1){
eval{
# заключаем в eval, чтобы не блокировалось на sysread
local $SIG{ALRM}=sub{die "ALRM"};
alarm 1; #
sysread($reader,$client,1024); # здесь пробовал разные варианты, но бкзрезультатно
chomp($client);
$C{$client}=$line; # собираем клиентов в хэш
$select->add($client);
print $client "OK\n"; # пытаемся послать клиенту сообщение, как это сделал родитель. Но не тут то было
alarm 0;
1;
};
# дальнейший код не имеет смысла, потому что манипулятор $client не передался от родителя
@s=$select->can_read(0);
foreach $sock (@s){
$rv=$sock->recv($data,1024,0);
if($data){
print "<p>$C{$sock}:$data\n";
}
}
foreach my $client(keys %C){
print $client $EOL; #
}
}
}[/codebox]
В принципе есть и другие реализации подобного сервера, и они у меня работают, но хочется разобраться с этим.
К примеру, когда дочерний процесс отщепляется для каждого клиента. Но при этом встает проблема контакта клиентов друг с другом. Нужно вести или общий файл или базу данных. А поскольку опрос клиентов идет с заданной задержкой, то появляются паузы. Если бы удалось реализовать эту схему, то пауз бы уже не было и по этой схеме можно было бы делать игровой сервер.
Буду благодарен за помощь.
Проблема в том, что не могу передать от родителя манимупулятор клиента.
[codebox]#!/usr/bin/perl
# Server
#
use CGI;
use CGI::Carp qw (fatalsToBrowser);
use IO::Socket;
use IO::Select;
use Time::HiRes qw(sleep); # короткие задержки
use IO::Handle; # для pipe
my $q=new CGI;
$|=1; # запрет буферизации
print $q->header(-type => 'text/html', -charset => 'windows-1251');
$select = IO::Select->new();
$server_port=8888;
$server=IO::Socket::INET->new(
LocalPort => $server_port,
Type =>SOCK_STREAM,
Reuse =>1,
Listen => 10
);
pipe($reader,$writer); # открываем канал к потомку
$writer->autoflush(1);
if($child3=fork()){ # отщепляем потомка
# блок родителя
while($client=$server->accept()){
my ($ip,$port,$host)=who_is($client);
print $writer $client; # эта строка должна передавать манипулятор клиента в дочерний процесс Worker, но не передает.
#Обыкновенный скаляр, к примеру $Hello успешно передает.
# Worker НЕ ВИДИТ КЛИЕНТА
# В этом проблема!!!!!!!!!
$Hello="$ip:$port\n";
print $client "Parent $Hello"; # эта строка успешно возвращается клиенту
print "<p>Parent: $Hello ";
}
}else{
# Блок потомка Worker
while(1){
eval{
# заключаем в eval, чтобы не блокировалось на sysread
local $SIG{ALRM}=sub{die "ALRM"};
alarm 1; #
sysread($reader,$client,1024); # здесь пробовал разные варианты, но бкзрезультатно
chomp($client);
$C{$client}=$line; # собираем клиентов в хэш
$select->add($client);
print $client "OK\n"; # пытаемся послать клиенту сообщение, как это сделал родитель. Но не тут то было
alarm 0;
1;
};
# дальнейший код не имеет смысла, потому что манипулятор $client не передался от родителя
@s=$select->can_read(0);
foreach $sock (@s){
$rv=$sock->recv($data,1024,0);
if($data){
print "<p>$C{$sock}:$data\n";
}
}
foreach my $client(keys %C){
print $client $EOL; #
}
}
}[/codebox]
В принципе есть и другие реализации подобного сервера, и они у меня работают, но хочется разобраться с этим.
К примеру, когда дочерний процесс отщепляется для каждого клиента. Но при этом встает проблема контакта клиентов друг с другом. Нужно вести или общий файл или базу данных. А поскольку опрос клиентов идет с заданной задержкой, то появляются паузы. Если бы удалось реализовать эту схему, то пауз бы уже не было и по этой схеме можно было бы делать игровой сервер.
Буду благодарен за помощь.