Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TransmitFile, Как другая сторона примет файл? 
:(
    Опции темы
Johen
  Дата 9.6.2005, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 25.5.2004
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Есть такая функция в Windows Sockets как TransmitFile.

Описание в MSDN здесь.

Вопрос такой: допустим сервер передает клиенту файл, с помощью каких средств клиент принимает файл? Какие функции клиент должен использовать, чтобы нормально этот файл принять?

Желателен пример кода. smile
PM MAIL ICQ   Вверх
UncleBob
Дата 10.6.2005, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 6.6.2005
Где: vo.spb.ru

Репутация: нет
Всего: нет



Я думаю, что это можно выполнить с помощью обычного метода чтения сокета - recv.
PM MAIL   Вверх
Johen
Дата 14.6.2005, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 25.5.2004
Где: Санкт-Петербург

Репутация: нет
Всего: нет



А поконкретней можно? Если через recv, то тогда зачем нужна вообще функция TransmitFile()? Можно используя send передавать файло...

Я думаю здесь recv не поможет...
PM MAIL ICQ   Вверх
UncleBob
Дата 14.6.2005, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 6.6.2005
Где: vo.spb.ru

Репутация: нет
Всего: нет



Цитата(Johen @ 14.6.2005, 13:46)
зачем нужна вообще функция TransmitFile()?

The TransmitFile function transmits file data over a connected socket handle. This function uses the operating system's cache manager to retrieve the file data, and provides high-performance file data transfer over sockets.

Ну и как ты сделаешь то же самое через обычный send?

Добавлено @ 16:26
Цитата(Johen @ 14.6.2005, 13:46)
Я думаю здесь recv не поможет...

Уверен в обратном.
PM MAIL   Вверх
Johen
Дата 17.6.2005, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 25.5.2004
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Тогда что-то вроде этого:
сервер: fread() -> send() ->
клиент: recv() -> fwrite()

smile
PM MAIL ICQ   Вверх
UncleBob
Дата 20.6.2005, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 6.6.2005
Где: vo.spb.ru

Репутация: нет
Всего: нет



Цитата(Johen @ 17.6.2005, 17:10)
Тогда что-то вроде этого:

Я бы сделал так:

1. На сервере формируешь заголовок. Для простоты фиксированной длины

Код

#pragma pack(push)
#pragma pack(1)

typedef struct tag_MyFileHeader
{
  // имя файла
  char szFileName[256];    
  // длина
  DWORD dwLength; 
}MyFileHeader;

#pragma pack (pop)


2. Коннектишься, открываешь файл, отсылаешь файл:

Код

int SendFileBySocket (char szFileName, SOCKET hSocket)
{
  BOOL bRes;

  HANDLE hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  
  if (INVALID_HANDLE_VALUE != hFile)
  {
    MyFileHeader mfh = {0};
    strncpy (mfh.szFileName, szFileName, 256);
    mfh.dwLength = GetFileSize (hFile, NULL);

    TRANSMIT_FILE_BUFFERS tfb = 
    {
      &mfh,         // заголовок
      sizeof (mfh), // длина заголовка
      NULL,         // "хвостовик" не используем
      0             // 
    };

    bRes = TransmitFile (
                          hSocket,        // идентификатор сокета
                          hFile,          // хэндл файла
                          0,              // послать файл целиком
                          0,              // размер посылки - по умолчанию
                          NULL,           // не использовать OVERLAPPED
                          &tfb,           // заголовки
                          TF_DISCONNECT   // разорвать соединение после отсылки
                        ); 

    CloseHandle (hFile);
  }
  else
    return GetLastError();

  return bRes ? ERROR_SUCCESS : WSAGetLastError ();
}


3. Принимаешь файл:

Код

int ReceiveFile (SOCKET hSocket)
{
  MyFileHeader mfh = {0};

  int nReceived = 0;
  int nReceivedHeader = 0;

  while (nReceivedHeader < sizeof (mfh))
  {
    nReceived = recv (hSocket, (char*)&mfh + nReceivedHeader, nReceivedHeader - sizeof (mfh), 0);
    if (SOCKET_ERROR == nReceived)
      return WSAGetLastError ();
    
    if (0 == nReceived)
      return WSAECONNRESET; // хедер не дочитан - сэмулируем обрыв связи

    nReceivedHeader += nReceived;
  }

  HANDLE hFile = CreateFile (mfh.szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);

  if (INVALID_HANDLE_VALUE == hFile)
    return GetLastError ();

  int nRes = ERROR_SUCCESS;
  
  do 
  {
    // Проверяем, хватит ли места на диске. Если нет - зачем принимать файл - лишний траффик
    SetFilePointer (hFile, mfh.dwLength, NULL, FILE_BEGIN);
    if (!SetEndOfFile (hFile))    
    {
      nRes = GetLastError();
      break;
    }

    SetFilePointer (hFile, 0, NULL, FILE_BEGIN);

    int nReceivedFile = 0;
    char TempBuf [4096];

    while (ERROR_SUCCESS == nRes && nReceivedFile < mfh.dwLength)
    {
      nReceived = recv (hSocket, TempBuf, 4096, 0);

      if (SOCKET_ERROR == nReceived)
        nRes = WSAGetLastError ();
      else if (0 == nReceived)
        nRes = WSAECONNRESET; // файл не дочитан - сэмулируем обрыв связи
      else
      {
        DWORD dwWritten;
        if (!WriteFile (hFile, TempBuf, nReceived, &dwWritten, NULL))
          nRes = GetLastError ();

        nReceivedFile += nReceived;
      }
    }

    if (ERROR_SUCCESS == nRes)
    {
      // по идее здесь recv должен вернуть 0, т.к. файл уже прочитан из сокета целиком
      nReceived = recv (hSocket, TempBuf, 1, 0); 

      if (0 != nReceived)
        nRes = WSAEMSGSIZE; // наиболее подходящая по смыслу ошибка
    }
  } 
  while(0);
  
  CloseHandle (hFile);
  
  return nRes;
}


4. Писал не проверяя, мобыть налажал smile

Это сообщение отредактировал(а) UncleBob - 20.6.2005, 11:03
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1685 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.