简体   繁体   中英

Winsock: recv() on Server is blocking, but client has already moved past send()

I am working on a project for school and have run into the following problem. My server is blocking out on recv() despite my client already sending its full message.

This is what I want to happen:

Server        Client
recv() <----  send()
send() ---->  recv()

This is what is happening:

Server        Client
recv() <----  send()
recv() -----  recv()

Some Background

2 Weeks ago I created the client by itself with an already coded server application. When I coded the client it functioned properly with the provided server, so I want to say that the client is wrong, but I don't know how to get the server that I coded to recognize that no more data will be coming in.

Code

Here is the code that I believe is relevant:

Client:

    bytesSent = 0;
    retVal = send(sock, phrase, msgLen, 0);
    bytesSent = retVal;
    while (bytesSent < msgLen) {
        retVal = send(sock, phrase + bytesSent, msgLen - bytesSent, 0);
        if (retVal == SOCKET_ERROR) {
            DisplayFatalErr("send() function failed.");
            exit(1);
        }
        bytesSent += retVal;
        // May need to re-call send in order to keep sending the data.

    }

...

    bytesRead = 0;
    while (bytesRead < msgLen) {
        retVal = recv(sock, rcvBuffer, RCVBUFSIZ - 1, 0);
        if (retVal <= 0) {
            DisplayFatalErr("recv() function failed.");
            exit(1);
        }
        bytesRead += retVal;
        for (int i = 0; i < retVal; i++) {
            printf("%c", rcvBuffer[i]);
        }
    }

Server:

    char* rcvBuffer[RCVBUFSIZ]; // RCVBUFSIZ = 50
    char* msg = "";
    int bytesRead = 0;
    do {
        if ((bytesRead = recv(clientSock, rcvBuffer, RCVBUFSIZ - 1, 0)) == 0) {
            break;
        }
        if (bytesRead < 0) {
            return -1;
        }
        char* msgConcatenated;
        int msgLen = strlen(msg);
        msgConcatenated = malloc(msgLen + bytesRead);
        if (msgConcatenated != NULL) {
            int newMsgLen = strlen(msgConcatenated);
            strncpy_s(msgConcatenated, newMsgLen, msg, msgLen);
            strncat_s(msgConcatenated, newMsgLen, rcvBuffer, bytesRead);
            msg = msgConcatenated;
        }
    } while (bytesRead != 0);

Let me know if I need to provide extra information.

When using TCP , to signal the other end of the socket that no more data will be sent, a packet with the FIN flag set must be sent. This is accomplished in Winsock by calling the function shutdown with SD_SEND as the second parameter. This will cause the program on the other end of the socket to no longer block when calling recv . Instead, recv will return 0 indicating that the connection has been gracefully closed (unless there is data left that has not been read yet). See the Microsoft documentation on the shutdown function for further information. This documentation page also contains some helpful information about graceful socket closure.

Also, as has been pointed out in the comments, your code contains a memory leak in the following line:

msg = msgConcatenated

In that line, you reassign msg without first freeing the memory that msg is pointing to. Unfortunately, fixing that memory leak is not easy, because you can't simply call free on msg before reassigning it. This is because, in the first iteration of the loop, msg can also be pointing to something else than dynamically allocated memory. Therefore, to fix the leak, you would also have to keep track of what type of memory msg is pointing to, or make it always point to dynamically allocated memory, even when the string is empty (ie when it only contains the terminating null character).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM