Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сокет сервер. Как передать потомку манипулятор клиента?  (Прочитано 9295 раз)
0 Пользователей и 1 Гость смотрят эту тему.
AndyT
Гость
« : 16-06-2008 14:35 » new

Пишу сокет сервер. При запуске сервера родитель Parent отщепляет процесс  Worker. Сам Parent висит в блокирующем режиме и ловит подключения. Поймав клиента он передает его в Worker. Worker крутится в бесконечном цикле, каждую секунду опрашивая своих клиентов. Если от кого-то поступает сообщение, он тут же рассылает его всем остальным.
Проблема в том, что не могу передать от родителя манимупулятор клиента.
Код:
#!/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; #
}
}
}
В принципе есть и другие реализации подобного сервера, и они у меня работают, но хочется разобраться с этим.
К примеру, когда дочерний процесс отщепляется для каждого клиента. Но при этом встает проблема контакта клиентов друг с другом. Нужно вести или общий файл или базу данных. А поскольку опрос клиентов идет с заданной задержкой, то появляются паузы. Если бы удалось реализовать эту схему, то пауз бы уже не было и по этой схеме можно было бы делать игровой сервер.
Буду благодарен за помощь.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 16-06-2008 15:42 » 

AndyT, создавай рабочий процесс после получения соединения - так будет проще.

Передавать дескриптор файла можно через unix-сокет, но не могу сказать, как это сделать в perl. Посмотри модуль POSIX, unix-сокеты и операции fcntl.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
AndyT
Гость
« Ответ #2 : 16-06-2008 16:06 » 

Передавать дескриптор файла можно через unix-сокет,
Ок. Посмотрю. С Unix-сокетами еще не общался, считал что незачем. Если будут еще соображения, пиши.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 16-06-2008 16:17 » 

Зачем соображения - почитай теорию. Дело в том, что Perl не может предоставить больше возможностей, чем дает их ОС и нужно знать, что можно и как что работает. Например, под виндой unix-сокеты будут работать только в среде MinGW, т.к. в винде нет полноценного аналога, а MinGW эммулирует Unix-окружение для программ, использующих ее.

Почитай про сетевые коммуникации. Рекомендую Ричарда Стивенсона - TCP/IP Illustrated, Volume 1: The protocols. Там узнаешь больше о сокетах, их поведении, а за одно - о unix-сокетах и их фичах.
https://club.shelek.ru/viewfiles.php?id=39

Можно ли сделать в Perl передачу дескриптора - это пока открыты вопрос. По любому, ты можешь передать открытые файлы дочернему процессу сделав fork() после открытия файла или создания сетевого подключения. Это относится и к слушающему сокету, но тут есть нюансы поведения, когда несколько процессов слушают один и тот же сокет.
« Последнее редактирование: 16-06-2008 16:19 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines