Winsock:服务器上的 recv() 正在阻塞,但客户端已经移过 send()
Winsock: recv() on Server is blocking, but client has already moved past send()
我正在为学校做一个项目,运行 遇到了以下问题。尽管我的客户端已经发送了完整的消息,但我的服务器正在阻止 recv()。
这就是我想要发生的事情:
Server Client
recv() <---- send()
send() ----> recv()
这是正在发生的事情:
Server Client
recv() <---- send()
recv() ----- recv()
一些背景知识
2 周前,我使用已经编码的服务器应用程序自行创建了客户端。当我对客户端进行编码时,它在提供的服务器上正常运行,所以我想说客户端是错误的,但我不知道如何让我编码的服务器识别出不会有更多数据进入。
代码
这是我认为相关的代码:
客户:
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]);
}
}
服务器:
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);
如果我需要提供额外的信息,请告诉我。
使用时 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 还包含一些有关优雅套接字关闭的有用信息。
此外,正如评论中所指出的,您的代码在以下行中包含 memory leak:
msg = msgConcatenated
在那一行中,您重新分配了 msg
,而没有先释放 msg
指向的内存。不幸的是,修复内存泄漏并不容易,因为您不能在重新分配之前简单地在 msg
上调用 free
。这是因为,在循环的第一次迭代中,msg
也可以指向动态分配内存之外的其他内容。因此,要修复泄漏,您还必须跟踪 msg
指向的内存类型,或者使其始终指向动态分配的内存,即使字符串为空(即当它只包含终止空字符)。
我正在为学校做一个项目,运行 遇到了以下问题。尽管我的客户端已经发送了完整的消息,但我的服务器正在阻止 recv()。
这就是我想要发生的事情:
Server Client
recv() <---- send()
send() ----> recv()
这是正在发生的事情:
Server Client
recv() <---- send()
recv() ----- recv()
一些背景知识
2 周前,我使用已经编码的服务器应用程序自行创建了客户端。当我对客户端进行编码时,它在提供的服务器上正常运行,所以我想说客户端是错误的,但我不知道如何让我编码的服务器识别出不会有更多数据进入。
代码
这是我认为相关的代码:
客户:
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]);
}
}
服务器:
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);
如果我需要提供额外的信息,请告诉我。
使用时 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 还包含一些有关优雅套接字关闭的有用信息。
此外,正如评论中所指出的,您的代码在以下行中包含 memory leak:
msg = msgConcatenated
在那一行中,您重新分配了 msg
,而没有先释放 msg
指向的内存。不幸的是,修复内存泄漏并不容易,因为您不能在重新分配之前简单地在 msg
上调用 free
。这是因为,在循环的第一次迭代中,msg
也可以指向动态分配内存之外的其他内容。因此,要修复泄漏,您还必须跟踪 msg
指向的内存类型,或者使其始终指向动态分配的内存,即使字符串为空(即当它只包含终止空字符)。