我有发送者和接收者。当我在同一台计算机上尝试时,接收方可以正确接收图像,但是当在另一台计算机上执行发送方时,接收方接收到的图像会失真。其他都正确接收(整数、字符数组……)
接收者:
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);
这里是扭曲的图像,
上面只有一小部分是正确的。我该如何解决这个问题?
最佳答案
在TCP ,不需要以相同的结构(作为 block )发送和接收数据。使用 TCP 发送的数据可以在接收时拆分为多个数据包或从多个数据包中组合。这种修改可以发生在您的计算机和目标计算机之间的任何地方(即在路由器中)。
还值得注意的是,recv
不会等到所有缓冲区都被填满。它尽可能多地获取并返回它接收到的大小。结果可能会发生以下执行:
关于发送部分:
int sent = send(socket, bufPtr, 100, 0);
std::cout << "Bytes sent: " << sent << std::endl;
输出:
Bytes sent: 15
在接收部分:
int received = recv(socket, bufPtr, 100, 0);
std::cout << "Bytes received: " << received << std::endl;
输出:
Bytes received: 5
您必须确保使用某种数据包结构接收所有数据。即
2-byte packetId | 4-byte packetLength | variable-byte packetData
通常在同一台机器上发送/接收不会修改数据包,因此您的代码可以正常工作。另一方面,发送到远程端点,协议(protocol)功能如 Nagle's algortihm来玩修改你的数据。
不要禁用 nagle 来解决问题,因为它仍然不能保证数据包不会被修改。这就是 TCP 的工作原理。它是一个流媒体协议(protocol)。
您可以使用 UDP ,数据包在该协议(protocol)中作为 block 发送和接收,无需修改。但是 UDP 缺少对数据是否正确传递的验证,更不用说检查它是否完全传递了。
关于c++ - OpenCV - 套接字接收到失真图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22377468/