winsock recv () дублирует / пропускает данные

Я пишу простую программу сервер / клиент для отправки файла с клиента на сервер.
я использую winsock2. Я ограничиваю возможность отправки данных каждый раз до 5000.

сторона клиента (отправить):

int iResult = 0;
int totalBytesSent = 0;

while (length > 0){
iResult = send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 ); // MAX_TRANSIT_SIZE is 5000
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
return closeSocket();
}
totalBytesSent += iResult;
length -= iResult;
//cout << "Data sent (" << iResult << " Bytes)" << endl;
}
cout << "Total Bytes Sent: (" << totalBytesSent << ")" << endl;

return 0;

на стороне сервера (recv):

    // Receive and send data
char recvbuf[MAX_DATA_SIZE];

int iResult = 0;
int totalBytesRead = 0;

// Receive until the peer shuts down the connection

do {
totalBytesRead += iResult;
iResult = recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);

if (iResult > 0) {
//printf("RECEIVED DATA\n");
//printf("Bytes received: %d\n", iResult);

} else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(_clientSocket);
WSACleanup();
return 1;
}

} while (iResult > 0);

cout << "Total Bytes Received: (" << totalBytesRead << ")" << endl;

Эта проблема:

После запуска клиента и сервера и отправки файла, он говорит правильный размер данных, отправленных / полученных (что, конечно, размер файла в байтах), НО выходной файл отличается, и когда я открываю его в каком-то текстовом редакторе (notepad ++ Я ясно вижу, что выходной файл содержит меньше данных (но File-> Properties показывает те же размеры файлов), а некоторые данные дублируются.

Мой вопрос:

Как работает revc ()? Если он получает данные во многих вызовах, накапливается ли он в буфере? (В моем случае: recvbuf) или он переписывает буфер?
Насколько я понял, он накапливается, поэтому мой код правильный ??

Благодарю.

1

Решение

В вашем коде есть несколько проблем.

Сторона клиента:

send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 );
  • Здесь вы никогда не обновляете data для учета уже отправленных байтов, поэтому каждый раз, когда вы звоните send он отправляет одни и те же данные снова и снова (первый MAX_TRANSIT_SIZE байты вашего data буфер). Быстрое исправление, если предположить data указатель на любой тип байта (uint8_t, char, …) будет:

    send( _connectSocket, data + totalBytesSent, MAX_TRANSIT_SIZE, 0 );

  • Вы также должны ограничить размер отправляемых данных, потому что если length изначально кратно MAX_TRANSIT_SIZE у вас будет переполнение буфера, когда вы достигнете конца данных:

    send( _connectSocket, data + totalBytesSent, std::min(length, MAX_TRANSIT_SIZE), 0 );


Сторона сервера:

recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);
  • Так же, как с send, recv не имеет понятия «что я уже получил в этом буфере». Поэтому каждый раз, когда вы звоните recv он просто помещает новые данные, которые он получает, в начало вашего буфера, перезаписывая старые данные. Это может или не может быть тем, что вы хотите, это трудно сказать, так как вы не показываете нам, как вы используете этот буфер. Возможно, вы захотите использовать тот же подход для управления вашим буфером приема, чем тот, который я только что объяснил для вашего буфера отправки.
2

Другие решения

Я не вижу, где вы пишете из recvbuf. Каждый раз, когда вы вызываете recv, он перезаписывает то, что уже есть в recvbuf. Поэтому, если у вас есть закомментированные распечатки «RECEIVED DATA», вы должны копировать данные, которые вы хотите сохранить в буфере.

2

По вопросам рекламы [email protected]