0

I am using windows sockets with c++. In the following call I am trying to reply a message to the socket that just connected.

I tried connecting using a dummy client in c++. It would connect but the recv() would not receive anything.

Then I tried using telnet, it worked instantly, just as i wanted.

SOCKET s = accept(ls, (sockaddr*)&clientSin, &s_len);

            if (s == INVALID_SOCKET) {
                cerr << "Error in accept call: " << WSAGetLastError();
            }
            else {
                cout << "Connection accepted at , socket no. :" << s << endl;
                //adding to list of incoming sockets
                inactiveList.push_back(s);
                //send message to client requesting credentials
                char buff[10];
                
                // the character 'x' is a code to the client to provide the server with the credentials
                buff[0] = 'x';
                buff[1] = '\0';
                //send(s, buff, 2, 0);
                if (send(s, "From Vic: ", 10, 0) == INVALID_SOCKET)
                {
                    int errorcode = WSAGetLastError();
                    cerr << "send to client failed: " << errorcode << endl;
                    closesocket(s);
                    continue;
                }
                Sleep(1000);
                if (send(s, "From Vic: ", 10, 0) == INVALID_SOCKET)
                {
                    int errorcode = WSAGetLastError();
                    cerr << "send to client failed: " << errorcode << endl;
                    closesocket(s);
                    continue;
                }
                
            }

the recv code is:

tnb = 0;
    while ((nb = recv(s, &buff[tnb], LINESZ - tnb, 0)) > 0)
    {
        tnb += nb;
    }
    /* If there was an error on the read, report it. */
    if (nb < 0)
    {
        printf("recv failed: %d\n", WSAGetLastError());
        return 1;
    }
    if (tnb == 0)
    {
        printf("Disconnect on recv");
    }
    /* Make the response NULL terminated and display it.  Using C output */
    printf("tnb = %d\n", tnb);
    buff[tnb] = '\0';
    puts(buff);
puru
  • 17
  • 6
  • Your `send` code is probably fine. Please show your `recv` code. – selbie Dec 22 '20 at 00:12
  • 1
    Unrelated to your issue. A failed `send` call doesn't return INVALID_SOCKET, it returns SOCKET_ERROR. They are probably both the same. – selbie Dec 22 '20 at 00:15
  • You should explicitly check for `tnb >= LINESZ` in your recv loop for breaking out. On windows, length is signed, but everywhere else the len parameter to recv is unsigned. – selbie Dec 22 '20 at 00:20
  • Did you at least add a printf statement in your while loop on the recv side? – selbie Dec 22 '20 at 00:21
  • 1
    Also, don't forget to null terminate `buff` before printing it. Otherwise, you risk printing out more than what you actually received for that line. – selbie Dec 22 '20 at 00:23
  • 1
    My psychic powers suggset that LINESZ is way bigger than what you are actually sending. Hence, it just stays in the loop forever waiting for more data. – selbie Dec 22 '20 at 00:27
  • What is your proof that "recv() would not receive anything"? The shown code loops until `recv`() returns 0 or the buffer size is exceeded. Until that happens `recv()` gets repeatedly called. What is the proof you can show of this not happening, for some reason? – Sam Varshavchik Dec 22 '20 at 00:27
  • Also, not checking if `recv` explicitly returns 0. I amended my answer below to cover this case as well. – selbie Dec 22 '20 at 00:35

1 Answers1

0

Taking all my comments and turning it into an answer.

I suspect your recv loop is continuing forever because you haven't sent enough data to make it break out of the loop.

Change this:

while ((nb = recv(s, &buff[tnb], LINESZ - tnb, 0)) > 0)
{
    tnb += nb;
}

To this: (notice that I'm allocating +1 for the array buff)

char buff[LINESZ+1]; // +1 for null terminator
buff[0] = '\0';
tnb = 0;
while (tnb < LINESZ)
{
    nb = recv(s, &buff[tnb], LINESZ-tnb, 0);
    if (nb < 0)
    {
        printf("Error on socket: %d\n", (int)WSAGetLastError());
        break;
    }
    else if (nb == 0)
    {
        printf("Remote socket closed\n");
        break;
    }

    printf("Received: %d bytes\n", (int)nb);

    tnb += nb;
    buff[tnb] = '\0'; // null terminate the end of the buffer so it will print reliably
}
selbie
  • 100,020
  • 15
  • 103
  • 173
  • This works however, is there a way in which you can break out of the loop without the socket closing. My server sends the message, but the client is on a loop and just keeps listening even when there is no more message coming. – puru Dec 22 '20 at 01:06
  • You need to build that into your own protocol. Add your own delimiters between messages. For example, scan the buffer you receive and look for a `'\n'` char – selbie Dec 22 '20 at 01:40