nixp.ru v3.0

20 октября 2017,
пятница,
06:26:48 MSK

DevOps с компанией «Флант»
DiverD написал 25 декабря 2006 года в 22:14 (1204 просмотра) Ведет себя неопределенно; открыл 7 тем в форуме, оставил 8 комментариев на сайте.

Вот код, я не могу сделать что бы клиенты которые конектятся могли видеть сообщение друг друга, для конекта можна использовать telnet.

#!/usr/bin/perl
#use strict;
use diagnostics;
use Socket;
use IO::Handle;
use constant PORT => 44444;
my @child = ();
SERVER->autoflush(1);
socket(SERVER,AF_INET,SOCK_STREAM,scalar getprotobyname('tcp')) or die "socket() failed : $!\n";
setsockopt(SERVER,SOL_SOCKET,SO_REUSEADDR,1) or die "setsockopt() failed : $!\n";
my $sockIp = sockaddr_in(PORT,INADDR_ANY);
bind(SERVER,$sockIp) or die "bind() failed : $!\n";
listen(SERVER,SOMAXCONN) or die "listen() failed : $!\n";
print "Server port:",PORT,"\n";
pipe(R,W);
R->autoflush(1);
W->autoflush(1);
while(my $hisaddr = accept(CLIENT,SERVER)) {
    CLIENT->autoflush(1);
    next if $pid = fork();
    die "fork() failed : $!\n" unless defined($pid);
    close SERVER;
    close W;
    print while();
    close R;
    while() {
        chomp;
        print "[$$] Client say me : $_\n";
        print CLIENT "You PID=$$\n";
    }
    close CLIENT;
    exit(0);
} continue {
    close R;
    print W "OK\n";
    close W;
    print "[$$] Parent\n";
    close CLIENT;
}

Если законектился одн клиент, то все нормал, если более, ты вылетает еррор о том что уже те дескрипторы с которых нужна читать и записывать уже давно закрыты, как решить проблему?

$ ./server.pl
Server port:44444
[1101] Parent
OK
[1103] Client say me : 1
[1103] Client say me : 2
print() on closed filehandle W at ./ppc_s.pl line 38 (#1)
    (W closed) The filehandle you're printing on got itself closed sometime
    before now.  Check your control flow.
[1101] Parent
readline() on closed filehandle R at ./ppc_s.pl line 27 (#1)
    (W closed) The filehandle you're reading from got itself closed sometime
    before now.  Check your control flow.
[1105] Client say me : HELLO

как я пайпы не создавал или FIFO использовал и UNIX-сокеты, ошибочный результат один и тот же. Мне сказали что с форкам такая беда не получится, хотя я сомневаюсь. Грубо говря я пишу чат консольный, знаю что можна это решить при помощи IO::Select, но все же мне нужен этот вариант.

Может тут нужна блок где то делать, вообщем прошу помочь..

metal

ты создаешь pipe один раз и постоянно закрываешь его каналы. Когда конектится второй клиент канал уже закрыты. Вообще я не пойму идею этой программы. Напиши в комментариях как она должна работать.

DiverD

вот-вот.

Вообщем это должен быть что та вроде чата.

К серверу конектятся клиенты, один клиент отправил сообщение а другие его получили — вот.!

metal

Я не представляю как ты можешь обойтись без select. У тебя сервер должен делать два действия одновремменно, ждать новых клиентов и передавать сообщения между уже имеющимися. Варианты:

1)select;

2) Не знаю реализуемо ли это в perl, знаю его плохо. Читал у Стивенса что можно передавать дескриптор меджу процессами. Если это возможно в perl, создаешь два процесса сразу, один слушает сокет, второй обслуживает уже подключившихся. При подключении, первый процесс передает дескриптор второму и дальше слушает. Второй соответствено подключает нового клиента к чату. Но все равно тебе не обойтись без select во втором процессе, можно конечно делать polling, но select точно лучше.

DiverD

ok, передача дискриптора возможна, с select-ом 100% получиться, проста я думал можна обайтись без него.

спаисбо, буду разбираться.

Feuerbach
metal
Читал у Стивенса что можно передавать дескриптор меджу процессами.

Лихо это у Стивенса. Можно пример в студию?

Насколько я знаю, передача дескрипторов возможна лишь в результате fork.

metal

Смотри главу 14.7 «Unix разработка сетевых приложений», вроде бы можно найти исходники примеров к ней в электронном виде.

Feuerbach

Нету у меня Стивенса. Сырцы скачал с

http://www.kohala.com/start/unpv12e/unpv12e.tar.gz

но найти там сорс к конкретной главе не представляется возможным.