Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.02.2010, 17:43   #1
hiho
Форумчанин
 
Регистрация: 29.04.2008
Сообщений: 100
По умолчанию Прием файлов TCP

Достались в наследство исходники клиент-серверного приложения. Причем клиент написан на дельфях, а сервер на С++.
Необходимо организавать передачу файлов от клиента к серверу, с условием "чтобы срочно, а то без премии останешься".
Пробовал отправять так:
Код:
    FS := TFileStream.Create('Путь к файлу',fmOpenRead);
    MainForm.Client.Socket.SendText('name' + 'Путь куда сохраняем');
    MainForm.Client.Socket.SendText('size' + IntToStr(FS.Size));
    FS.Position := 0;
    MainForm.Client.Socket.SendStream(FS);
А принимал:
Код:
while ((memset(buff, 0, sizeof(buff) / sizeof(buff[0]))) && 
(bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) && bytes_recv != SOCKET_ERROR)
{
     if ((buff[0] == 's') && (buff[1] == 'i') && (buff[2] == 'z') && (buff[3] == 'e'))
     {
          //Получаем сведения о размере передаваемого файла
          char temp[100];
          int i;
          for(i = 4; i<=strlen(buff); i ++) temp[i-4] = buff[i];
          temp[i-4] = '\0';
          size = atoi(temp);
     } else if ((buff[0] == 'n') && (buff[1] == 'a') && (buff[2] == 'm') && (buff[3] == 'e'))
        {
             for(int i = 4; i<=100; i ++) name[i-4] = buff[i];
             File = fopen(name,"wb");//Где FILE *File объявлен ранее
        } else
           {
                fwrite(buff, bytes_recv, 1, File);
        sizeR += bytes_recv;//Переменная sizeR содержит колличество принятых байт
        if (sizeR == size) 
                        {
              fclose(File);
              MessageBox(0,"Файл принят успешно",name,0); 
        }
            }
}
При передаче файла по IP 127.0.0.1 все работает как положено, а когда выпускаю на просторы локальной или глобальной сетей постоянно пишет меньше чем положено на несколько килобайт, и соответственно происходит зависание.

Может есть у кого какие нибудь соображения как лучше передавать и принимать файлы.
hiho вне форума Ответить с цитированием
Старый 10.02.2010, 18:39   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,087
По умолчанию

Ситуация такая. TCP протокол не пакетный а потоковый. Отправляем мы килобайт одной командой, а в пункт назначения эти данные прийдут по очереди. Сначала первый килобайт, потом еще 2 килобайта и остаток потом подтянется. Проверка на строку "size" уже "опасна", т.к. чисто теоретически может прийти сначала "siz", а следующий вызов recv уже прочитает оставшуюся "e". Обычно реализуют что-то вроде пакетов на базе TCP. Прописывают заголовок и как-то помечают где пакет кончается (в заголовок, например, добавляется размер передаваемых данных).
Соответственно, сначала принимаем по сети заголовок:
Код:
// Заголовок
struct Header
{
  char name[255];
  int size;
};
...
// Приём заголовка
int byte_recv = 0; // Число принятых байт
int header_size = sizeof(Header); // размер заголовка
Header header; // заголовок
char *head = (char*) &header; // Указатель на область с заголовком, чтобы можно было адресоваться к нужным байтам заголовка
while (byte_recv != header_size) // пока не приняли весь заголовок целиком
{
  recv(my_sock, head[byte_recv], header_size - byte_recv, 0)); // принимаем оставшиеся байты
}
И в таком же духе потом принимаем сам файл.
Кроме того, в WinSock есть функция специальная для передачи файла по сети. Что-то вроде FileTransfer (уже не помню как она называется).
Ну и можно глянуть тут
pu4koff вне форума Ответить с цитированием
Старый 10.02.2010, 20:09   #3
hiho
Форумчанин
 
Регистрация: 29.04.2008
Сообщений: 100
По умолчанию

Не знал. Спасибо за ликбез, после сдачи программы обязательно почитаю маны по протоколам.
P.S. Нашел эту функцию. TransmitFile называеться, и как я ее раньше не заметил. Передает файлы замечательно, только по моему ограничение у нее в 2 гб.

Проблема решена.

Последний раз редактировалось hiho; 10.02.2010 в 21:57.
hiho вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
запись на прием Kardi PHP 6 22.09.2012 16:00
"2540:TCP"= 2540:TCP:oeiuq AlexSh Безопасность, Шифрование 0 06.07.2009 10:28
Прием SMS SERG1980 Свободное общение 0 04.10.2007 16:10