简体   繁体   English

Winsock:服务器上的 recv() 被阻塞,但客户端已经移过 send()

[英]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.尽管我的客户端已经发送了完整的消息,但我的服务器在 recv() 上被阻塞了。

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. 2 周前,我使用已经编码的服务器应用程序自行创建了客户端。 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.当使用TCP时,要向套接字的另一端发出不再发送数据的信号,必须发送一个设置了 FIN 标志的数据包。 This is accomplished in Winsock by calling the function shutdown with SD_SEND as the second parameter.这在 Winsock 中通过使用 SD_SEND 作为第二个参数调用 function shutdown来完成。 This will cause the program on the other end of the socket to no longer block when calling recv .这将导致套接字另一端的程序在调用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).相反, recv将返回 0 表示连接已正常关闭(除非还有尚未读取的数据)。 See the Microsoft documentation on the shutdown function for further information.有关详细信息,请参阅有关关闭 function 的 Microsoft 文档 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:此外,正如评论中所指出的,您的代码在以下行中包含memory 泄漏

msg = msgConcatenated

In that line, you reassign msg without first freeing the memory that msg is pointing to.在该行中,您无需先释放msg指向的 memory 就重新分配msg Unfortunately, fixing that memory leak is not easy, because you can't simply call free on msg before reassigning it.不幸的是,修复 memory 泄漏并不容易,因为在重新分配之前不能简单地在msg上调用free This is because, in the first iteration of the loop, msg can also be pointing to something else than dynamically allocated memory.这是因为,在循环的第一次迭代中, msg还可以指向动态分配的 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).因此,要修复泄漏,您还必须跟踪msg指向的 memory 类型,或者使其始终指向动态分配的 memory,即使字符串为空(即,它仅包含终止 Z37A6259CC4891DAE02 字符) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C 中的客户端和服务器 send() 和 recv() - Client and Server send() and recv() in C 同时执行recv()和send()winsock - Do both recv() and send() winsock send()到特定的客户端C WInSock - send() to specific client C WInSock C、recv_all、send_all 中的 TCP 回显服务器/客户端 - 由我实现,recv 不起作用 - TCP echo server / client in C, recv_all, send_all - implemented by me, recv does not work Winsock客户端和服务器将无法连接 - Winsock client and server wont connect 如果服务器关闭,则阻止recv调用挂起 - Blocking recv call hangs if server is down 如何在客户端服务器应用程序中异步发送文件?(在C中使用winsock2.h) - How can i send files asynchronously in a client-server application?(using winsock2.h, in C) 使用Winsock将文件分解成块,然后以二进制形式从客户端发送到C中的服务器吗? - Break a file into chunks and send it as binary from client to server in C using winsock? 如何在 udp 服务器(在 c 中)和 udp 客户端(python)之间发送和接收 c 结构? - how to send and recv c struct between udp server(in c) and udp client(python)? 有什么方法可以知道从客户端发送到服务器的字节数并在网络中处理 recv() - Is there any way to know the amount of bytes send from the client to the server and process the recv() in networks
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM