2

I have sender and receiver. When I try in same computer, receiver receives image correctly but when execute sender in another computer, receiver receives distorted images. Others are correctly received (integer, char array ...)

receiver:

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);

sender:

rec.imageSize = av.mImg.total()*av.mImg.elemSize();
bytes_sent = send(socketfd, av.mImg.data, rec.imageSize, 0);

Here the distorted image,

distortedImage

Only a small part is correct at top. How can i fix this?

Ulfsark
  • 902
  • 1
  • 11
  • 26
  • See the answer here http://stackoverflow.com/questions/20314524/c-opencv-image-sending-through-socket/20321262#20321262 might be helpful. – Haris Mar 13 '14 at 12:08
  • 1
    Put your `recv` inside a loop that runs until all bytes are received. – Mark Setchell Dec 31 '14 at 18:25

1 Answers1

1

In TCP, data is not required to be sent and received in the same structure (as a block). A data sent using TCP can be split to or combined from multiple packets on receive. This modification can happen anywhere between your computer and destination computer (i.e. in router).

It is also worth noting that recv does not wait until all the buffer is filled. It fetches as much as it can and it returns the size that it received. As a result the following execution may happen:

On the sending part:

int sent = send(socket, bufPtr, 100, 0);
std::cout << "Bytes sent: " << sent << std::endl;

Outputs:

Bytes sent: 15

And on the receiving part:

int received = recv(socket, bufPtr, 100, 0);
std::cout << "Bytes received: " << received << std::endl;

Outputs:

Bytes received: 5

TCP on Wikipedia

You have to make sure you are receiving all the data, using some kind of packet structure. i.e.

2-byte packetId | 4-byte packetLength | variable-byte packetData

Usually sending/receiving on the same machine does not modify the packets so you code works. On the other hand, sending to a remote endpoint, protocol features like Nagle's algortihm come to play to modify your data.

Do not disable nagle to solve the issue as it will still not be guaranteed that packets will not be modified. That is how TCP works. It is a streaming protocol.

You can use UDP, packets are sent and received as blocks without modification in that protocol. But UDP is missing the verification that the data is delivered correctly let alone checking if it is delivered at all.

UDP on Wikipedia

Etherealone
  • 3,488
  • 2
  • 37
  • 56