OpenCV - полученное сокетом искаженное изображение

У меня есть отправитель и получатель. Когда я пробую на том же компьютере, получатель получает изображение правильно, но когда выполняет отправителя на другом компьютере, получатель получает искаженные изображения. Другие правильно принимаются (целое число, массив символов...)

получатель:

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

Здесь искаженное изображение,

distortedImage

Только небольшая часть верна сверху. Как я могу это исправить?

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

TCP в Википедии

Вы должны убедиться, что вы получаете все данные, используя какую-то структуру пакетов. т.е.

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

Обычно отправка / получение на одной и той же машине не изменяет пакеты, поэтому ваш код работает. С другой стороны, отправляя на удаленную конечную точку, функции протокола, такие как алгоритм Nagle, начинают действовать для изменения ваших данных.

Не отключайте nagle для решения проблемы, так как все равно не будет гарантировано, что пакеты не будут изменены. Вот как работает TCP. Это потоковый протокол.

Вы можете использовать UDP, пакеты отправляются и принимаются как блоки без изменений в этом протоколе. Но UDP пропускает проверку, что данные доставлены правильно, не говоря уже о проверке, доставлены ли они вообще.

UDP в Википедии

Другие вопросы по тегам