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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с асинхронным WSARecv в winsock  (Прочитано 11427 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
Robinson
Интересующийся

ru
Offline Offline

« : 18-02-2011 22:14 » 

Здравствуйте.

Пишу клиент для TCP. Задача - приконнектиться к серверу и принимать/получать сообщения. Вот код рабочего потока:
Код:

void tcp_client::exec(void)
{
char buffer[MAX_RECV_BUFFER_SIZE];
WSABUF sendBuf, recvBuf;
recvBuf.buf = buffer;
recvBuf.len = MAX_RECV_BUFFER_SIZE;

bool bStop = false;
DWORD bytes_transferred = 0;
int rc, err = 0;
DWORD flags = 0;
DWORD wait_result;

while(!bStop)
{
int recv_result = WSARecv(socket, &recvBuf, 1, NULL, &flags, &hRecvOverlapped, NULL);

int gle = WSAGetLastError();

if(recv_result != 0 && gle != WSA_IO_PENDING)
{
std::cout << "WSARecv failed with error: " << WSAGetLastError() << std::endl;
break;
}

wait_result = WaitForMultipleObjects(3, hArr, FALSE, INFINITE); // hArr - HANDLE hArr[3] = {StopEvent, hRecvOverlapped.hEvent,  SendEvent};

switch(wait_result)
{
case WAIT_OBJECT_0: // stop

bStop = true;
break;

case WAIT_OBJECT_0 + 1: // receive

if(!WSAGetOverlappedResult(socket, &hRecvOverlapped, &bytes_transferred, FALSE, &flags))
{
bStop = true;
break;
}
if(bytes_transferred > 0)
{
                                  /* ...  */
}
else if(bytes_transferred == 0)
{
!!!
}
break;

case WAIT_OBJECT_0 + 2: // send
                
                        /* ... */

default:
break;
}
}

shutdown(socket, SD_BOTH);
closesocket(socket);
socket = NULL;

SetEvent(hStoppedEvt);
}

Проблема собственно в том, что при закрытии сервера (при shutdown и closesocket) в клиенте WSARecv возвращает -1, WSAGetLastError() - WSA_IO_PENDING и событие в hRecvOverlapped в сигнальном состоянии, т.е. WaitForMultipleObjects сразу возвращает 1 -> switch переходит в case receive и так дальше по кругу и бегает, WaitForMultipleObjects не ждет. Вроде при разрыве коннекта WSARecv должен ошибку возвратить, а возвращает WSA_IO_PENDING... Подскажите, пожалуйста, почему так происходит и как с этим бороться? Заранее спасибо за ответы...
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #1 : 18-02-2011 22:21 » 

А зачем ловить события, если сокет ты уже закрыл?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Robinson
Интересующийся

ru
Offline Offline

« Ответ #2 : 19-02-2011 12:26 » 

Сокет закрывается на сервере. Вопрос в том как правильно сделать, чтобы при разрыве соединения клиент как-то на это реагировал (выводил сообщение, пытался заново приконектиться например). В моем случае получается так что при падении сервера клиент постоянно получает пакеты с нулевой длинной...
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #3 : 19-02-2011 12:38 » 

Если данных во входном буфере нет то и делать ничего не нужно - просто закрыть.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Robinson
Интересующийся

ru
Offline Offline

« Ответ #4 : 19-02-2011 12:42 » 

Вы имеете ввиду просто рассматривать приход пакета с нулевой длинной как ошибку?

Остается вопрос, почему WSARecv не возвращает ошибку, говорящую о разрыве соединения?
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #5 : 19-02-2011 12:44 » 

Да. При работе с сокетами без WSA так и есть - чтение возвращает нулевую длину.
Закрытие сокета - это не ошибка, а штатная ситуация.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Robinson
Интересующийся

ru
Offline Offline

« Ответ #6 : 19-02-2011 14:19 » 

а как же WSAEDISCON ? В MSDN пишут что в случае разрыва связи с другой стороны WSARecv вернет именно её...
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #7 : 19-02-2011 14:21 » new

У нас есть статья по сокетам - просмотри.
https://club.shelek.ru/viewart.php?id=325
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines