Winsock recv()复制/丢失数据
winsock recv() duplicates/missing data
我正在编写一个简单的服务器/客户端程序,将文件从客户端发送到服务器。我正在使用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: %dn", 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 DATAn");
//printf("Bytes received: %dn", iResult);
} else if (iResult == 0)
printf("Connection closing...n");
else {
printf("recv failed: %dn", WSAGetLastError());
closesocket(_clientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
cout << "Total Bytes Received: (" << totalBytesRead << ")" << endl;
问题:
在运行客户端和服务器并发送文件后,它确实说发送/接收的正确数据大小(当然是以字节为单位的文件大小),但输出文件不同,当我用一些文本编辑器(notepad++)打开它时,我可以清楚地看到输出文件持有较少的数据(但文件->属性显示相同的文件大小)和一些数据是重复的。
我的问题:
revc()是如何工作的?如果它在许多调用中接收数据,它是否在缓冲区中积累数据?(在我的情况下:recvbuf)还是它重写缓冲区?据我所知,它确实积累,所以我的代码是正确的??
谢谢。
你的代码中有几个问题。
客户端:send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 );
这里你永远不会更新
data
来考虑已经发送的字节,所以每次你调用send
时,它都会一次又一次地发送相同的数据(data
缓冲区的第一个MAX_TRANSIT_SIZE
字节)。一个快速修复,假设data
是一个指针到任何字节类型(uint8_t, char,…)将是:send( _connectSocket, data + totalBytesSent, MAX_TRANSIT_SIZE, 0 );
你还应该限制你发送的数据大小,因为除非
length
最初是MAX_TRANSIT_SIZE
的倍数,否则当你到达数据的末尾时,你会有缓冲区溢出:send( _connectSocket, data + totalBytesSent, std::min(length, MAX_TRANSIT_SIZE), 0 );
服务器端:
recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);
- 就像
send
一样,recv
没有"我已经在缓冲区中收到了什么"的概念。因此,每次调用recv
时,它只是将接收到的新数据放在缓冲区的开头,覆盖旧数据。这可能是也可能不是你想要的,这很难判断,因为你没有向我们展示你是如何使用缓冲的。你可能想使用与我刚才解释的发送缓冲区相同的方法来管理你的接收缓冲区。
我看不出你写在哪里了。每次调用recv时,它都会覆盖recvbuf中已经存在的内容。因此,在您有注释掉的"RECEIVED DATA"打印的地方,您应该复制您想要保留在缓冲区之外的数据。
- 矢量如何将数据复制到另一个矢量?
- 将矢量的数据复制到<MyStruct>矢量<MyStruct>的指针
- 将父类的子类的数据复制到具有相同父类的另一个类
- 使用 memcpy 将矢量数据复制到 wstring 的正确方法
- C++:传递指向函数中类的指针会导致数据复制?
- 将数据复制到磁盘上新位置的语法
- pybind11:如何包装以 std::vector<double> 为参数以避免数据复制的 C++ 函数
- 如何将数据复制到字节数组的某些部分
- 使用Sapera拍摄图像并将数据复制到矢量
- 如果strncpy将随机数据复制到缓冲区中会发生什么
- C++ 促进序列化、构造函数和数据复制
- 将一个通道数据复制到OpenCV中的另一个通道
- SSE将数据复制到变量
- doxygen将doxygen注释中的特定数据复制到markdown页面中
- 正在将指针指向的数据复制到另一个指针中
- 使用 CUDA 将大数据复制到 GPU 和从 GPU 复制大数据
- 尝试将.csv数据复制到c++中的结构时出现堆栈溢出错误
- 数据复制与封装
- 如何将 frontBuffer 数据复制到纹理 DirectX 9
- 更快地将数组中的数据复制到目标,同时应用缩放或偏移因子