Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Win32 API - [решено] WinSock

Ответить
Настройки темы
Win32 API - [решено] WinSock

Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Изменения
Автор: ganselo
Дата: 30-07-2009
Здравствуйте!
Есть сервер на котором установлена прога (серверная часть). Клиенты посылают запросы серверу на скачку файлов.
Пытаюсь написать клиентскую часть, но возникают проблемы с приёмом файлов. Вот кусок кода, где осуществляется приём и запись:
Код: Выделить весь код
//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).
Кто нибуть знает почему не правильно приходят или я не так записываю бинарные файлы?

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 18:59, 30-07-2009

 
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Используешь асинхронную операцию на файлах и забываешь синхронизировать запись/чтение. Сделай двойную буфферизацию с синхронизацией или пиши синхронно:
Код: Выделить весь код
// Асинхронное с синхронизацией

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

Отправлено: 07:58, 31-07-2009 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Решил использовать синхронную операцию на файлах. Всё равно не работало на бинарных файлах...
После второй выпитой бутылки пива, всё таки решил эту проблему.
Оказалось всё дело в функции 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);
}

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 11:50, 31-07-2009 | #3



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Win32 API - [решено] WinSock

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Интернет - [решено] Проблема с каталогом поставщиков Winsock. (Повреждён DNS-клиент?) ТатьянаИ Microsoft Windows 2000/XP 7 14-10-2009 16:59
Интернет - пропала NETSH winsock Legat Microsoft Windows 2000/XP 1 28-08-2007 11:45
Работа с WinSock Guest Программирование и базы данных 3 08-04-2004 22:19
winsock Greyman Сетевые технологии 1 21-02-2004 20:55




 
Переход