Войти

Показать полную графическую версию : [решено] WinSock


ganselo
30-07-2009, 18:59
Здравствуйте!
Есть сервер на котором установлена прога (серверная часть). Клиенты посылают запросы серверу на скачку файлов.
Пытаюсь написать клиентскую часть, но возникают проблемы с приёмом файлов. Вот кусок кода, где осуществляется приём и запись:


//command[0] = "File", command[1] = FileName - заголовок приходящий от сервера.
if(command[0] == "File")
{
//создаём поток для записи файла
HANDLE hThread = CreateThread(NULL, 0, DownloadThread, command[1].c_str(), 0, NULL);
if(hThread == INVALID_HANDLE_VALUE)
{
....
}
....
CloseHandle(hThread);
}
//===================================================================
DWORD WINAPI DownloadThread(LPVOID lpParam)
{
LPTSTR Param = (LPTSTR)lpParam;
char recvBuff[4097];
SOCKET sock;
HANDLE hFile;
OVERLAPPED ovlp;

char FileName[MAX_PATH] = "C:\\";
strcat(FileName, Param);
.....
.....
//Создаём файл
hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//запускаем цикл, где считываем сообщения от сервера.
while(1)
{
int ret = recv(sock, recvBuff, sizeof(recvBuff), 0);
if(ret == 0 || ret == SOCKET_ERROR) break;

recvBuff[ret] = '\0';

ovlp.Offset = GetFileSize(hFile, 0);
ovlp.OffsetHigh = 0;
ovlp.hEvent = NULL;

//записываем в файл
WriteFile(hFile, recvBuff, strlen(recvBuff), 0, &ovlp);
}
CloseHandle(hFile);
closesocket(sock);
.....
}

Проблема в том, что текстовые файлы приходят нормально, а бинарные нет.
Точно знаю, что серверная часть работает нормально и серверная часть отсылает файл с помощью функции TransmitFile (mswsock.h).
Кто нибуть знает почему не правильно приходят или я не так записываю бинарные файлы?

pva
31-07-2009, 07:58
Используешь асинхронную операцию на файлах и забываешь синхронизировать запись/чтение. Сделай двойную буфферизацию с синхронизацией или пиши синхронно:

// Асинхронное с синхронизацией

char mem[0x2000];
OVERLAPPED ovlp[2];
...
char *buf1=mem, *buf2=mem+0x1000;

for(bool is_active = true; is_active; std::swap(buf1, buf2))
{
int ret = recv(sock, buf1, 0x1000, 0);
...
// т.к. ovlp.hEvent=0 при попытке записать что-то в файл одновременно
// (в разные концы файла например), могут происходить неверные срабатывания
// функции GetOverlappedResult. SDK рекомендует использовать hEvent
unsigned long dw_transferred = 0;
GetOverlappedResult(hFile, &ovlp, &dw_transferred, true);
WriteFile(hFile, recvBuff, strlen(buf1), 0, &ovlp);
}

// синхронное

for(bool is_active = true; is_active;)
{
int ret = recv(sock, buf, 0x1000, 0);
...
unsigned long dw_transferred = 0;
WriteFile(hFile, recvBuff, strlen(buf), &dw_transferred, 0);
}

ganselo
31-07-2009, 11:50
Решил использовать синхронную операцию на файлах. Всё равно не работало на бинарных файлах...
После второй выпитой бутылки пива, всё таки решил эту проблему.
Оказалось всё дело в функции strlen()

WriteFile(hFile, recvBuff, strlen(recvBuff), 0, 0);

Если файл текстовый то strlen() срабатывает нормально, а если бинарные данные то результат был непредсказуемый (иной раз strlen() возвращала результат в 2 раза больше нужного).
А нужно было так:

while(1)
{
int ret = recv(sock, recvBuff, sizeof(recvBuff), 0); //recv(...) возвращает длину данных, записанных в recvBuff
....
WriteFile(hFile, recvBuff, ret, 0, 0);
}




© OSzone.net 2001-2012