У меня есть отправитель и получатель. Когда я пробую на том же компьютере, получатель получает изображение правильно, но когда выполняет отправитель на другом компьютере, получатель получает искаженные изображения. Другие правильно получены (целое число, массив символов …)
получатель:
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, данные не должны быть отправлены и получены в той же структуре (как блок). Данные, отправленные с использованием 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 для решения проблемы, так как все равно не будет гарантировано, что пакеты не будут изменены. Вот как работает TCP. Это протокол потоковой передачи.
Ты можешь использовать UDP, пакеты отправляются и принимаются как блоки без изменений в этом протоколе. Но UDP пропускает проверку, что данные доставлены правильно, не говоря уже о проверке, доставлены ли они вообще.
Других решений пока нет …