recv не останавливается после получения функции transFile ()

Я пишу небольшой File / Transfer FileTransfer, используя Winsocket для класса, и он в основном работает, за исключением того, что я не могу больше получать сообщения на сокете после того, как я получил файл и записал его на свой жесткий диск.

Код передачи выглядит так:

    long size = GetFileSize(hFile, NULL);
TransmitFile(_socket, hFile, size, 0, NULL, NULL, TF_DISCONNECT);
ok = ::recv(_socket, cantwortfilename, 100, 0); // getting a confirmation (1)
cantwortfilename[ok] = '\0';
cout << cantwortfilename << endl;
char test[] = "ok!";
::send(_socket, test, strlen(test), 0); // to test if server receives again (2)

Я попробовал это с 0 вместо размера с теми же результатами.

Теперь для получения на стороне сервера:

    HANDLE hFile = CreateFile(filepathlong, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

while (1)
{
ReadFile((HANDLE)_socket, &buffer, MAX_PATH, &dwbr, &AsyncInfo);
GetOverlappedResult((HANDLE)_socket, &AsyncInfo, &dwbr, TRUE);
if (dwbr == 0) break;
WriteFile(hFile, buffer, dwbr, &dwbr, NULL);
}
char test[] = "alles ok!";
::send(_socket, test, strlen(test), 0); // sending the confirmation (1)

CloseHandle(hFile);

i = ::recv(_socket, test, 10, 0); // receiving the test (2)
test[i] = '\0';
cout << "empfangen:" << test << endl;

Насколько я могу судить, передача файла работает нормально (пробовал rar jpg .h) и

::send(_socket, test, strlen(test), 0); // sending the confirmation (1)

выходит тоже хорошо.

но получение после этого мне ничего не дает? или что-то пустое?
Я думаю, что-то пустое, так как recv не блокирует программу тоже.
Но «я» будет 0, когда я его выдаю.

чтобы проверить, не сделал ли я какую-то ошибку с материалом в цикле while (1), я попробовал другой способ получить файл.

2-я попытка:

    int r;
ofstream file(filepath, std::ios::out | std::ios::binary | std::ios::trunc);
char *memblock;
int size = 7766; // was the size of the file i was testing with
memblock = new char[size];
memset(memblock, 0, size);
if (file.is_open()){
//while memory blocks are still being received
while ((r = recv(_socket, memblock, 256, 0)) != 0)
{
//if there's a socket error, abort
if (r == SOCKET_ERROR)
{
cout << "error" << endl;
}
//write client's file blocks to file on server
file.write(memblock, r);
}
delete[] memblock;
//finished sending memory blocks; file is completely transferred.
file.close();
}

после этого снова отправьте recv с тем же результатом.
Файл работал, но получение снова принесло мне что-то пустое.

Так может кто-нибудь сказать мне, почему и как это можно исправить? Если возможно с наименьшим возможным изменением?

Спасибо,
Мартин

РЕДАКТИРОВАТЬ: код, который работает для меня сейчас:

    char csize[256];
rc = recv(_socket, csize, 256, 0);
csize[rc] = '\0';
int size = atoi(csize);
int bytes_read = 0, len = 0;

int r;
ofstream file(filepath, std::ios::out | std::ios::binary | std::ios::trunc);
char *memblock;
memblock = new char[size];
memset(memblock, 0, size);

if (file.is_open()){
while (bytes_read < size){
len = recv(_socket, memblock + bytes_read, size - bytes_read, 0);
bytes_read += len;
}
file.write(memblock, size);
delete[] memblock;
file.close();
}

1

Решение

Ваш передатчик звонит TransmitFile() с TF_DSCONNECT флаг. Это закроет сокет после завершения отправки файла. Передатчик не может отправить больше данных один раз TransmitFile() вышел (я не уверен, если TransmitFile() только полудуплекс закрывается, чтобы закрыть только направление отправки, но оставляет направление приема открытым, или если он делает полнодуплексное закрытие как в направлениях отправления, так и в направлении приема — я бы допустил ошибку с осторожностью и предположил бы последнее).

Исходя из того, что вы показали, вам нужно использовать shutdown() а также closesocket() вместо TF_DISCONNECT так что у вас больше контроля над тем, когда и как происходит отключение.

Также, TransmitFile() не отправляет размер файла, только данные файла, поэтому ваш получатель не может узнать, когда данные файла фактически закончились, пока он не ожидает истечения времени ожидания (что не является надежным решением). Вам нужно изменить свой передатчик так, чтобы он отправлял размер файла перед отправкой данных файла, затем измените свой получатель, чтобы сначала прочитать размер файла, а затем зацикливаться, пока он не получит указанное количество байтов.

0

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


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