Здраствуйте. Я пишу сервер и столкнулся с проблемой определения состояния соединения с клиентом. По идеи клиент подсоединяется к серверу и получает оттуда команды. У меня проблема в том что записи для отключивщихся клиентов мне надо удалять. Тоесть мне нужно определить отключился ли клиент или нет. В голову лезут какието бредовые мысли типа реализация пинг-понг ( я ему пинг, он мне понг, если понг не пошёл значит отконектился). Интересует как реализована подобная проверка в других приложениях. Помогите пожалуста.
Код (Text): if (recv(sock, buf, len, MSG_PEEK) == SOCKET_ERROR && WSAGetLastError() == WSAENOTCONN) { // client disconnected }
Да. Кажется это то что мне нужно было. Сейчас буду пробывать. Спасибо. А почему тогда в ирке реализован механизм типа пинг понг ?
Хотя нет. Поидеи же всёравно придётся создавать ешё один сокет, со всеми вытекаюшими отсюда вызовами. Есть ли реальный способ использования одного и тогоже сокета без блокировки его ? Или пинг понг оптимальный вариант ?
Лучше так и делать. Хотя (возможно я ошибаюсь) у сокета TCP можно установить время через которое будет проверятся жив ли клиент... Посмотри: Функция ioctlsocket параметр SIO_KEEPALIVI_VALS
KEEPALIVE таймер есть во всех нормальных реализациях tcp/ip (в том числе во всех версиях винды). Так что заботиться о проверке специально не надо, система это умеет делать сама.
SnugForce Спасибо за подсказку по поводу ioctlsocket. Ms Rem Очень интересно. А можно ли сделать так чтобы когда клиент отсоединялся система передавала управление на мою функцию ?
Когда клиент отсоединяется, если он послал FIN, то функция recv возвращает 0, а если связь разорвана из за сбоя, то -1. Можешь юзать WSaEventSelect и получать через него события, но это немного неудобная модель. Удобнее использовать просто select.
Ms Rem А если на том конце кебель просто порвут или сетевой шнур "отойдет" Кстати проверно, хотя на стандартных ком-тах, без вызова ioctlsocket - сообщение о разрыве не приходит (( Ой, забыл сказать, что SIO_KEEPALIVE_VALS для одного сокета, а SIO_KEEPALIVE это записывается в реестр и будет действительно для ВСЕХ процессов т.е. для всех сокетов. Соот-но SIO_KEEPALIVE_VALS поддерживается >win2000
во всяких vsftpd, apache и пр. есть замечательная опция конфига, насчёт timeout'а. И если apache не прочитал из сокета, и не вписал туда ничего, в течение timeout'а, то он его просто закрывает.
DeHunter Прошу прощения но почему бы не использовать событийную модель для таких целей? Для держания небольшог количества соединений подходит вполне. зы если пишешь прокси сервер то лучше и проще select нет
Да в том то и дело что по задумке соединений будет много. А если всё грамотно сделаю то очень много =). Долбился вчера с этим селектом. Чтото не получилось у меня. В мсдне както описанно не понятно ( ну по крайнемере я не понял ). Покажите пример использования селекта ?
DeHunter Если очень много, то только порты завершения, на каждый процессор в системе можно будет создать поток с рабочит портом завершения. Вот пример селекта Код (Text): FD_ZERO macro fds mov fds.fd_count,ebx endm FD_SET macro hSocket,fds mov eax,hSocket mov ecx,fds.fd_count shl ecx,2 mov fds.fd_array[ecx],eax inc fds.fd_count endm mov timewait.tv_sec,30 ; maximal wait time is 30 seconds mov timewait.tv_usec,ebx .while 1 invoke Sleep,100 FD_ZERO fds FD_SET SocketsArray.client,fds FD_SET SocketsArray.server,fds invoke select,10h,addr fds,ebx,ebx,addr timewait .if eax!=SOCKET_ERROR invoke redirrect_data,SocketsArray.client,SocketsArray.server,a ddr fds .if !eax .break .endif invoke redirrect_data,SocketsArray.server,SocketsArray.client,a ddr fds .if !eax .break .endif .endif .endw