我有发件人和收件人。当我在同一台计算机上尝试时,接收器正确接收图像但在另一台计算机上执行发送器时,接收器接收失真的图像。其他正确接收(整数,字符数组......)
接收器:
char sockData[record.imageSize];
bytes_received = recv(new_sd, sockData, record.imageSize, 0);
cv::Mat img = cv::Mat::zeros(height,width,CV_8UC1);
memcpy(img.data, sockData, record.imageSize);
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(3);
customerFacePath << id << ".png";
cv::imwrite(customerFacePath.str().c_str(),img,compression_params);
发件人:
rec.imageSize = av.mImg.total()*av.mImg.elemSize();
bytes_sent = send(socketfd, av.mImg.data, rec.imageSize, 0);
这里是扭曲的图像,
顶部只有一小部分是正确的。我该如何解决这个问题?
答案 0 :(得分:1)
在TCP中,不需要在相同的结构(作为块)中发送和接收数据。使用TCP发送的数据可以在接收时从多个数据包中拆分或组合。此修改可以在您的计算机和目标计算机之间的任何位置进行(即在路由器中)。
值得注意的是,recv
不会等到所有缓冲区都被填满。它尽可能多地获取并返回它收到的大小。因此,可能会发生以下执行:
在发送部分:
int sent = send(socket, bufPtr, 100, 0);
std::cout << "Bytes sent: " << sent << std::endl;
输出:
发送的字节数:15
在接收部分:
int received = recv(socket, bufPtr, 100, 0);
std::cout << "Bytes received: " << received << std::endl;
输出:
收到的字节数:5
您必须确保使用某种数据包结构接收所有数据。即。
2-byte packetId | 4-byte packetLength | variable-byte packetData
通常在同一台机器上发送/接收不会修改数据包,因此您可以编码。另一方面,发送到远程端点,可以使用Nagle's algortihm等协议功能来修改数据。
不要禁用nagle来解决问题,因为仍然无法保证数据包不会被修改。这就是TCP的工作原理。它是流媒体协议。
您可以使用UDP,数据包作为块发送和接收,而无需在该协议中进行修改。但是UDP缺少正确传递数据的验证,更不用说检查它是否已经交付。