LINUX.ORG.RU

select. read. EAGAIN


0

0

Не могу понять такую картину...

есть accept на неблокирующем сокете. ловит содинение, появляется сокет соединения. Далее FD_SET. потом в цикле select. Бесконечный цикл все крутит select и read. Все хорошо, read возвращает -1 и errno=EAGAIN. Но тут наступает момент, когда клиент отваливается, но почему-то select все равно поднимает флаг, что есть сокет на обработку, а read упорно возвращает -1 и EAGAIN. Не пойму, каким образом поймать, что клиент уже отвалился от сокета?

Deleted

с него read или write вернёт ошибку, по-моему, от этого и отталкиваться. У меня та же фигня на линухе. Я так понял это происходит когда клиент штатно закрыл соединение.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

в том то и дело, read возвращает -1, но при этом errno = EAGAIN.

Deleted
()

Покажи код с селектом.

mv ★★★★★
()

man select

>Three independent sets of file descriptors are watched. Those listed in readfds will be watched to see if characters become available for reading (more precisely, to see if a read will not block; in particular, a file descriptor is also ready on end-of-file), those in writefds will be watched to see if a write will not block, and those in exceptfds will be watched for exceptions. On exit, the sets are modified in place to indicate which file descriptors actually changed status. Each of the three file descriptor sets may be specified as NULL if no file descriptors are to be watched for the corresponding class of events.

Four macros are provided to manipulate the sets. FD_ZERO() clears a set. FD_SET() and FD_CLR() respectively add and remove a given file descriptor from a set. FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.

!!! On exit, the sets are modified in place to indicate which file descriptors actually changed status. !!!

после выхода из select читаешь только те дескрипторы, которые остались в readfds (FD_ISSET()). Если на одном из таких read == -1 значит клиент отвалился. errno проверять, imho, не надо.

kamikadze
()
Ответ на: man select от kamikadze

>только те дескрипторы, которые остались в readfds (FD_ISSET())

именно так.

Если на одном из таких read == -1 значит клиент отвалился. errno проверять, imho, не надо.

нет, не так. при EAGAING read вернет -1. но я уже разобрался. нужно было проверять read == 0, то значит отвалился. иначе при неблокируемом сокете (в нормальном открытом состоянии) read должен возвращать либо > 0, либо -1 c errno = EAGAIN. если read == -1 и errno отличен от EGAIN, значит действительно случилось что-то неладное с сокетом и нужно его закрывать.

Deleted
()
Ответ на: комментарий от Deleted

Хм...

последний раз я с си селекторами сталkивался еще в прошлом веке :)

солярка или hpux, не помню уже точно... Там вроде работало просто с read == -1.

О, в исходниках явы можно наверное посмотреть как делать правильно. У них там для каждой OS свой враппер. Но мне лень. Работает и ладно...

kamikadze
()
Ответ на: Хм... от kamikadze

я не пытаюсь сделать, чтоб оное работало на всем зоопарке ОСей. Мне Linux и FreeBSD за глаза хватает. Даже винду не беру в расчет.

Deleted
()
Ответ на: комментарий от Deleted

Покажите код, здесь явно что-то не так.

Если клиент сделал close то read() вернет 0.
А write -1 и EPIPE

Если клиент помер то ошибка может быть ETIMEDOUT.


FD_ISSET делаете?
FD_SET на каждой итерации повторяте?
Ситуацию с таймаутом проверяете?

Покажите код ;)

OxiD ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.