четверг, 3 сентября 2015 г.

Winsock WSAEWOULDBLOCK

WSAEWOULDBLOCK  – возникает в результате когда принимающая сторона не успевает обработать буфер данных. Решить проблему можно, отлавливая событие FD_WRITE; Наиболее опасная ситуация возникает на стороне сервера. Например, рассмотрим такой код на стороне сервера:
bool WriteData(SOCKET hSocket, char * cbBuff, int nSize)
{

       int  MaxByteSend = nSize;
       int  Offset = 0;
       int  nError = 0;

       do
       {
             nError = send(hSocket, cbBuff + Offset, MaxByteSend, 0);

             if(nError <= 0)
             {
                    nError = WSAGetLastError();

                    if(nError == WSAEWOULDBLOCK)
                    {
                           printf("WriteData WSAEWOULDBLOCK\r\n");
                           continue;
                    }
                    else return false;

             }

             if(nError > 0)
             {
                    Offset += nError;
                    MaxByteSend -= nError;
             }

       } while(nError > 0 && MaxByteSend != 0);

        return Offset == nSize ? true : false;
}

На 1-ый взгляд не каких проблем, если возникает событие WSAEWOULDBLOCK то мы просто пробуем еще раз отправить данные. Но в этом-то и заключается вся суть проблемы! Во 1-ых сторона клиента может в этот момент не принимать данные, а обрабатывать предыдущую порцию. Сервер же будет золочен на срок, пока клиент не примет буфер!  Как способ выхода из данной ситуации, можно ввести переменную nTryCount = 0; и если мы получаем WSAEWOULDBLOCK увеличиваем nTryCount++; когда количество таких, попыток подряд достигнет N(например 3), завершаем процедуру отправки с кодом неудачи!...Далее когда SOCKET будет готов читать данные, мы получим событие FD_WRITE. И дошлем остальную часть буфера!

Второе решение проблемы это использовать полностью асинхронные сокеты.