Нашел у других код который определяет это через сигналы (сокеты в
ассинхронном режиме),
но не работает (проверяю через Cygwin), а именно не приходят сигналы IO.
В чём может быть дело.
Posted via RSDN NNTP Server 1.9 gamma
Re: как определить что клиент отсоединился от сокета
Здравствуйте, meandr, Вы писали:
M>Приветствую.
M>Собственно говоря вот и весь вопрос.
M>Нашел у других код который определяет это через сигналы (сокеты в M>ассинхронном режиме), M>но не работает (проверяю через Cygwin), а именно не приходят сигналы IO.
M>В чём может быть дело.
в select помещаешь дескриптор в exeption (третье) множество, при отключении клиента там получишь подтверждение
Re[2]: как определить что клиент отсоединился от сокета
но срабатывает такое:
если клиент отключается, то его сокет становится готовым на чтение,
но считывается с него 0 байт. Я смотрел и у других такое реализовано.
А разумное объеснение мне не видно
Posted via RSDN NNTP Server 1.9 gamma
Re[2]: как определить что клиент отсоединился от сокета
Здравствуйте, ilnar, Вы писали:
I>в select помещаешь дескриптор в exeption (третье) множество, при отключении клиента там получишь подтверждение
А если этот дескриптор присутствует в первых двух множествах, разве select не вернет ошибку о неверном дескрипторе?
newbie
Re[3]: как определить что клиент отсоединился от сокета
Здравствуйте, meandr, Вы писали:
M>Не работает такой метод, фиг знает почему,
M>но срабатывает такое: M> если клиент отключается, то его сокет становится готовым на чтение, M> но считывается с него 0 байт. Я смотрел и у других такое реализовано. M> А разумное объеснение мне не видно
0 — если не читать 0 байт (указать размер буфера 0), тоэто означает eof для сокета. а если не eof и данных нет, то вернется -1, и код ошибки вроде EAGAIN
Re[3]: как определить что клиент отсоединился от сокета
Здравствуйте, PVA, Вы писали:
PVA>Здравствуйте, ilnar, Вы писали:
I>>в select помещаешь дескриптор в exeption (третье) множество, при отключении клиента там получишь подтверждение PVA>А если этот дескриптор присутствует в первых двух множествах, разве select не вернет ошибку о неверном дескрипторе?
нет, я всегда в купе со чтением или записью (множествами) обязательно вношу и в третий, т.е. если ожидаю чтения, то чтение и третий, и т.д. :
Ну а всё таки почему обнаружение дисконекта не происходит в следующем коде:
А также вот такой вопрос: А правильно ли отправлять клиенту что — либо сразу после принятия соединения?
use POSIX;
use IO::Socket;
use IO::Select;
$|=1;
sub nonblock {
my $socket = shift;
$flags = fcntl($socket, F_GETFL, 0);
fcntl($socket, F_SETFL, $flags | O_NONBLOCK );
}
$SERVER = new IO::Socket::INET(LocalPort => 88,
LocalAddr => 0,
Timeout => 5,
Reuse => 1,
Listen => 5) or die "can't create socket";
nonblock($SERVER);
$list = new IO::Select ();
$list->add($SERVER);
while(1) {
foreach $fh ($list->can_read(0.05)) {
if($fh == $SERVER) {
if($new = $SERVER->accept()){
nonblock($new);
$list->add($new);
print "accept ".fileno($new)."\n";
print {$new} ("HTTP/1.1 200 ok\r\ncontent-type: text/plain;\r\n\r\n") || die($!."\n"); #правильно ли это делать сдесь?
};
}
else {
my $char;
Здравствуйте, meandr, Вы писали:
M>Ну а всё таки почему обнаружение дисконекта не происходит в следующем коде:
Потому что вы не проверяете на возниконовение exeption. Используйте метод select, а не can_read. В нём можно указать списки дескрипторов сразу для чтения, записи и исключений.
M>А также вот такой вопрос: А правильно ли отправлять клиенту что — либо сразу после принятия соединения?
В вашем случае, ИМХО, сначала нужно принять запрос, а потом уже отвечать.
M> print {$new} ("HTTP/1.1 200 ok\r\ncontent-type: text/plain;\r\n\r\n") || die($!."\n"); #правильно ли это делать сдесь?
Если уж вы пишете подобие Web-сервера, то отвечайте его кодами (я про die).
Нет ничего невозможного..
Re[3]: как определить что клиент отсоединился от сокета
Здравствуйте, meandr, Вы писали:
M>Не работает такой метод, фиг знает почему,
M>но срабатывает такое: M> если клиент отключается, то его сокет становится готовым на чтение, M> но считывается с него 0 байт. Я смотрел и у других такое реализовано. M> А разумное объеснение мне не видно
Во, и у меня те же грабли.
Только у меня 50/50: то как описано, то получаю ошибку сокета 10053.
Ну, да, раз говорите, что так и должно быть, щас диагностику допишу
K.T.G.
Re[4]: как определить что клиент отсоединился от сокета
Посмотрел сейчас man'ы, в exeption помещаются только дескрипторы, на которые пришли OOB данные. Если соединение закрывается, то срабатывает readset или writeset.
Нужно анализировать возврат функция чтения или записи.
M>И вы всё таки не отведили на мой вопрос, наверное непонятно сформулировал: M> Коректно ли сразу после выполнения accept произвести отправку чего либо, те: M> $fd accept (...); M> write ($fd, 'erwerwerwerwer');
Можно, если хотите. Если не хотите, можете подождать .
Нет ничего невозможного..
Re: как определить что клиент отсоединился от сокета
От:
Аноним
Дата:
08.09.04 22:37
Оценка:
Здравствуйте, meandr, Вы писали:
M>Приветствую.
M>Собственно говоря вот и весь вопрос.
M>Нашел у других код который определяет это через сигналы (сокеты в M>ассинхронном режиме), M>но не работает (проверяю через Cygwin), а именно не приходят сигналы IO.
M>В чём может быть дело.
SYNOPSIS
#include <sys/socket.h>
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);
DESCRIPTION
Getpeername returns the name of the peer connected to socket s. The namelen parameter
should be initialized to indicate the amount of space pointed to by name. On return it
contains the actual size of the name returned (in bytes). The name is truncated if the
buffer provided is too small.
Оно?
Re[3]: как определить что клиент отсоединился от сокета
meandr wrote:
> но срабатывает такое: > если клиент отключается, то его сокет становится готовым на чтение, > но считывается с него 0 байт. Я смотрел и у других такое реализовано.
На самом деле это стандартный и переносимый способ.
> А разумное объеснение мне не видно
Разумное объяснение в том, как происходит graceful close. Клиент вызвает shutdown(socket, SHUT_WR). Этот вызов отправляет серверу FIN и переводит сокет клиента в состояние FIN_WAIT_1. В этом состоянии клиент ждет ACK от сервера, который TCP стэк сервера посылает автоматом, поэтому в состоянии FIN_WAIT_1 клиент пребывает совсем недолго, если только нет никаких сетевых проблем. После получения FIN от клиента сокет сервера становится готовым на чтение (read event, о котором можно узнать при помощи poll или select) с 0 байт, что для сокета означает EOF. На полученный FIN TCP стэк сервера отсылает клиенту ACK и переходит в состояние CLOSE_WAIT. Сокет клиента, получив этот ACK от сервера переходит в состояние FIN_WAIT_2, ожидая FIN от сервера. Чтобы отослать клиенту FIN, сервер должен со своей стороны вызвать shutdown(socket, SHUT_WR).
В манах сказано, что close на серверном сокете автоматом делает shutdown, но в ходе экспериментов на red hat 9 было выяснено, что это не так и следует вызывать shutdown(socket, SHUT_WR) явно, иначе после close серверный сокет так и останется висеть в CLOSE_WAIT, а клиентский в FIN_WAIT_2 (т.е. будут orphan'ами).
-- Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re[5]: как определить что клиент отсоединился от сокета
Здравствуйте, butcher, Вы писали:
B>Здравствуйте, meandr, Вы писали:
B>Посмотрел сейчас man'ы, в exeption помещаются только дескрипторы, на которые пришли OOB данные. Если соединение закрывается, то срабатывает readset или writeset. B>Нужно анализировать возврат функция чтения или записи.