dimanche 26 avril 2015

Winsock invalid received byte number

I'm currently facing a Winsock related problem when trying to validate the number of received bytes.

In my application I'm using a non-blocking socket in order to throw my own Timeout exception. Here the according code for the initialization of Winsock:

// Initialize Winsock
WSAData winSockData;
WORD dllVersion = MAKEWORD(2, 1);
long iResult = WSAStartup(dllVersion, &winSockData);
if (iResult != NO_ERROR)
    return;

addrinfo* serverAddress = nullptr;
addrinfo* ptr = nullptr, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

iResult = getaddrinfo("127.0.0.1", "10011", &hints, &serverAddress);
if (iResult != 0)
    return;

// Create communication socket
SOCKET connectSocket = socket(AF_INET, SOCK_STREAM, /*IPPROTO_TCP*/0);
if (connectSocket == INVALID_SOCKET)
    return;

// Establish connection to server
iResult = connect(connectSocket, serverAddress->ai_addr, (int)serverAddress->ai_addrlen);
if (iResult == SOCKET_ERROR)
    return;

// Set socket to non-blocking
ULONG mode = 1;
m_iResult = ioctlsocket(m_connectSocket, FIONBIO, &mode);
if (m_iResult == SOCKET_ERROR)
    return;

// server address info not needed anymore
freeaddrinfo(serverAddress);

The application connects to a given telnet server first, sends a request and then awaits an according response message.

The incoming data gets stored in an appropriate char array, called m_serverMsg (with a fixed size of BUFSIZE, that is currently set at 4200 bytes).

If retrieving the server response message is taking to long (max. allowed time stored in g_requestTimeout), my own TimeoutException gets thrown.

Given server message has reached its end if a carriage return character (\r\n) has been found in the message buffer.

However, the following part for retrieving the server response message is not working as expected. Expected incoming data bytes are 1,040, but actual bytes are always 3,435,973,836.

unsigned long long startTime = getWallTimeInMs();
bool retry = true;
unsigned int receivedBytes = 0;
// Fetch server response
do
{

    try
    {

        m_iResult = fetchMessage(m_connectSocket, m_serverMsg, int(BUFSIZE - receivedBytes));
        if (m_iResult == SOCKET_ERROR)
            throw std::exception();

        if (m_iResult > 0)
        {
            for (unsigned int i = receivedBytes; i < receivedBytes + m_iResult; i++)
            {
                if (m_serverMsg[i] == '\r\n')
                {
                    retry = false;
                    break;
                }
            }

            receivedBytes += m_iResult;
        }
    }
    catch (CommException e)
    {
        // in case server response didn't arrive
        if (getWallTimeInMs() - startTime < g_requestTimeout)
            Sleep(20);
        else
            // response timeout exceeded; connection has been lost
            throw CommException("server not responding in time.", CommProblem::ConnectionLost);
    }
    catch (std::exception& e)
    {
        std::cout << "There was a socket related problem." << std::endl;
        std::cout << "Error code: " << WSAGetLastError() << std::endl;
    }

} while (retry);

Aucun commentaire:

Enregistrer un commentaire