我正在编写一个简单的服务器/客户端程序,用于将文件从客户端发送到服务器。 我正在使用winsock2。我限制每次发送数据的容量为5000。
客户端(发送):
int iResult = 0;
int totalBytesSent = 0;
while (length > 0){
iResult = send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 ); // MAX_TRANSIT_SIZE is 5000
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
return closeSocket();
}
totalBytesSent += iResult;
length -= iResult;
//cout << "Data sent (" << iResult << " Bytes)" << endl;
}
cout << "Total Bytes Sent: (" << totalBytesSent << ")" << endl;
return 0;
服务器端的(recv):
// Receive and send data
char recvbuf[MAX_DATA_SIZE];
int iResult = 0;
int totalBytesRead = 0;
// Receive until the peer shuts down the connection
do {
totalBytesRead += iResult;
iResult = recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);
if (iResult > 0) {
//printf("RECEIVED DATA\n");
//printf("Bytes received: %d\n", iResult);
} else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(_clientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
cout << "Total Bytes Received: (" << totalBytesRead << ")" << endl;
问题:
运行客户端和服务器并发送文件后,它确实说发送/接收的数据大小正确(当然是文件大小,以字节为单位),但是输出文件不同,当我用一些文本打开它时编辑器(记事本++)我可以清楚地看到输出文件包含较少的数据(但文件 - >属性显示相同的文件大小),而一些数据是重复的。
我的问题:
revc()如何运作?如果它在多次调用中接收数据,它是否会在缓冲区中累积它? (在我的情况下:recvbuf)还是重写缓冲区? 据我所知,它确实积累了,所以我的代码是正确的吗?
感谢。
答案 0 :(得分:2)
我看不出你在recvbuf写的地方。每次调用recv时,它都会覆盖recvbuf中已有的内容。因此,如果您有已注释掉的“RECEIVED DATA”打印件,则应该将要保留的数据复制到缓冲区之外。
答案 1 :(得分:2)
您的代码中存在多个问题。
客户端:
send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 );
此处,您永远不会更新data
以考虑已发送的字节数,因此每次调用send
时,它会一次又一次地发送相同的数据(第一个MAX_TRANSIT_SIZE
个字节你的data
缓冲区。快速修复,假设data
是指向任何字节类型(uint8_t,char,...)的指针将是:
send( _connectSocket, data + totalBytesSent, MAX_TRANSIT_SIZE, 0 );
您还应该限制发送的数据大小,因为除非length
最初为MAX_TRANSIT_SIZE
的倍数,否则当您到达数据末尾时,您将遇到缓冲区溢出:< / p>
send( _connectSocket, data + totalBytesSent, std::min(length, MAX_TRANSIT_SIZE), 0 );
服务器端:
recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);
send
一样,recv
没有“我在缓冲区中已经收到了什么”的概念。因此,每次调用recv
时,只需将其收到的新数据放在缓冲区的开头,就会覆盖旧数据。这可能是您想要的,也可能不是,这很难说,因为您没有告诉我们您如何使用该缓冲区。您可能希望使用相同的方法来管理接收缓冲区,而不是我刚才为发送缓冲区解释的那个。