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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Клиент-Сервер(асинхронный): передача файлов 
V
    Опции темы
Ash313374
Дата 15.8.2011, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Добрый день!
Пишу клиент и сервер с передачей текстового файла от клиента серверу. Задачу нужно решить с использованием неблокирующих сокетов. Всё в принципе работает, но файл почему-то передаётся не всегда, кроме того, если запускаю отдельно экзешники (т.е. не из билдера), то файл не передаётся вообще. Вот код клиента и сервера, и ещё приложен архив с проектом. Буду очень благодарна за помощь!

Клиент:

Код

//---------------------------------------------------------------------------
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
 
#include <conio.h>
 
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
 
#pragma argsused
 
WSADATA ws;//информация о сокете
 
int main(int argc, char* argv[])
{
 
   int sock;
   struct sockaddr_in addr;
 
   if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws)))
   {
       perror("WSAStartup");
       system("pause");
       exit(1);
   }
 
   sock=socket(AF_INET, SOCK_STREAM,0);
 
   if (sock<0)
   {
      perror("socket");
      system("pause");
      exit(2);
   }
 
   addr.sin_family=AF_INET;
   addr.sin_port=htons(666);
   addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
   if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
   {
       perror("connect");
       system("pause");
       exit(3);
   }
 
   FILE *F;
   if (!(F=fopen("1.txt","r")))
   {
      perror("Open File");
      system("pause");
      exit(4);
   };
 
   char s[80];
   char p[80];
 
   while(!feof(F))
   {
      fgets(s,80,F);
      send(sock, s,sizeof(s),0);
      recv(sock,p,sizeof(s),0);
      printf("%s",p);
   };
   printf("\nThe file transfer completed.\n");
   fclose(F);
   delete(F);
   F = NULL;
   closesocket(sock);
   system("pause");
   return 0;
}


Сервер:

Код

//---------------------------------------------------------------------------
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <algorithm>
#include <set>
using namespace std;
#include <time.h>
 
#include <conio.h>
#include <vcl.h>
#pragma hdrstop
 
//---------------------------------------------------------------------------
 
#pragma argsused
//---------------------------------------------------------------------------
int Number;
WSADATA ws;//информация о сокете
int main(int argc, char* argv[])
{
 
    // Шаг 1 - инициализация библиотеки Winsock
    if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws)))
    {
       perror("WSAStartup");
       system("pause");
       exit(1);
    }
 
    // Шаг 2 - создание сокета
    SOCKET sock, listener;
 
    struct sockaddr_in addr;
    char buf[1024];
    int bytes_read;
 
    listener = socket(AF_INET, SOCK_STREAM, 0);
    if(listener < 0)
    {
        perror("socket");
        system("pause");
        exit(2);
    }
    ULONG ulBlock;
    ulBlock = 1;
    //аналог fcntl
    if (ioctlsocket(listener, FIONBIO, &ulBlock) == SOCKET_ERROR)
    {
        perror("ioctlsocket_listener");
        system("pause");
        exit(3);
    }
 
    // Шаг 3 - установка соединения
    // заполнение структуры sockaddr_in
    // указание адреса и порта сервера
    addr.sin_family = AF_INET;
    addr.sin_port = htons(666);
    addr.sin_addr.s_addr = INADDR_ANY;
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        system("pause");
        exit(4);
    }
 
    listen(listener, 1);
 
    Number = 0;
 
    FD_SET ReadSet;
    int ReadySock;
 
    set<int> clients;
    clients.clear();
 
    // цикл извлечения запросов на подключение из
    // очереди
    while(1)
    {
       // Заполняем множество сокетов
       FD_ZERO(&ReadSet);
       FD_SET(listener, &ReadSet);
 
       for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
            FD_SET(*it, &ReadSet);
 
       // Задаём таймаут
       timeval timeout;
       timeout.tv_sec = 15;
       timeout.tv_usec = 0;
 
       // Ждём события в одном из сокетов
       int mx = max(listener, *max_element(clients.begin(), clients.end()));
 
       if ((ReadySock = select(mx+1, &ReadSet, NULL, NULL, &timeout)) ==
                SOCKET_ERROR)
       {
          perror("Select");
          system("pause");
          exit(6);
       }
 
       if (FD_ISSET(listener, &ReadSet))
       {
          sock = accept(listener, NULL, NULL);
          if (sock == INVALID_SOCKET)
          {
             perror("accept");
                break;
          }
 
          if (ioctlsocket(sock, FIONBIO, &ulBlock) == SOCKET_ERROR)
          {
              perror("ioctlsocket_sock");
              break;
          }
 
          //добавили в список
          clients.insert(sock);
       }
 
       for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
       {
          if(FD_ISSET(*it, &ReadSet))
          {
             Number++;   // увеличиваем счетчик
                   // подключившихся клиентов
             AnsiString filename;
             filename = "Res"+IntToStr(Number)+".txt";
 
             FILE *F;
             if (!(F = fopen(filename.c_str(),"w")))
             {
                 perror("Create File");
                 break;
             };
 
             while( (bytes_read = recv(*it, buf, 1024, 0))>0 )
             {
                fprintf(F,buf);
                printf(buf);
                // Отправляем данные обратно клиенту
                send(*it, buf, bytes_read, 0);
             }
 
             fprintf(F,"\0");
             fclose(F);
             delete(F);
             F = NULL;
             closesocket(*it);
             clients.erase(*it);
          }
 
          printf("\nReceiving the file %d is complete.\n",Number);
       }
 
 
    }
 
     closesocket(sock);
     closesocket(listener);
    _exit(0);
 
    return 0;
}
//---------------------------------------------------------------------------


Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  AClientServer.rar 674,28 Kb
PM MAIL   Вверх
Ash313374
Дата 16.8.2011, 22:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

Вот работающий код сервера.

Код
//---------------------------------------------------------------------------
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <algorithm>
//#include <set>
#include <map>
using namespace std;
#include <time.h>

#include <conio.h>
#include <vcl.h>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
//---------------------------------------------------------------------------
int Number;
WSADATA ws;//информация о сокете
int main(int argc, char* argv[])
{

    // Шаг 1 - инициализация библиотеки Winsock
    if (FAILED (WSAStartup (MAKEWORD( 1,1 ), &ws)))
    {
       perror("WSAStartup");
       system("pause");
       exit(1);
    }

    // Шаг 2 - создание сокета
    SOCKET sock, listener;

    struct sockaddr_in addr;
    char buf[1024];
    int bytes_read;

    listener = socket(AF_INET, SOCK_STREAM, 0);
    if(listener < 0)
    {
        perror("socket");
        system("pause");
        exit(2);
    }
    ULONG ulBlock;
    ulBlock = 1;
    //аналог fcntl
    if (ioctlsocket(listener, FIONBIO, &ulBlock) == SOCKET_ERROR)
    {
        perror("ioctlsocket_listener");
        system("pause");
        exit(3);
    }

    // Шаг 3 - установка соединения
    // заполнение структуры sockaddr_in
    // указание адреса и порта сервера
    addr.sin_family = AF_INET;
    addr.sin_port = htons(666);
    addr.sin_addr.s_addr = INADDR_ANY;
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        system("pause");
        exit(4);
    }

    listen(listener, 1);

    Number = 0;

    FD_SET ReadSet;
    int ReadySock;

    map <int,AnsiString> clients;
    clients.clear();

    //typedef:
    typedef map<int,AnsiString>::value_type valType;

    // цикл извлечения запросов на подключение из
    // очереди
    while(1)
    {

       /*DWORD dwExitCode;
       HANDLE hThreatf = _beglntnread(...);
       GetExitCodeThread(hThread &dwExitCode);
       CloseHandle(hThread);

       _beginthread( void (__cdecl *stait_address)(void *), unsigned stack_size, void *arglist);
       */

       // Заполняем множество сокетов
       FD_ZERO(&ReadSet);
       FD_SET(listener, &ReadSet);

       //for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
       for(map<int,AnsiString>::iterator it = clients.begin(); it != clients.end(); it++)
            FD_SET((*it).first , &ReadSet);

       // Задаём таймаут
       timeval timeout;
       timeout.tv_sec = 15;
       timeout.tv_usec = 0;

       int mx = listener;
       for(map<int,AnsiString>::iterator it = clients.begin(); it != clients.end(); it++)
       {
          if ((*it).first > listener)
             mx = (*it).first;
       };

       // Ждём события в одном из сокетов

       if ((ReadySock = select(mx+1, &ReadSet, NULL, NULL, &timeout)) ==
        SOCKET_ERROR)
       {
          perror("Select");
          system("pause");
          exit(6);
       }

       if (FD_ISSET(listener, &ReadSet))
       {
          sock = accept(listener, NULL, NULL);
      if (sock == INVALID_SOCKET)
      {
         perror("accept");
             //system("pause");
             break;
          }

          if (ioctlsocket(sock, FIONBIO, &ulBlock) == SOCKET_ERROR)
          {
              perror("ioctlsocket_sock");
              //system("pause");
              break;
          }

          //добавили в список
          Number++;   // увеличиваем счетчик
                   // подключившихся клиентов
          clients.insert( valType(sock,"Res"+IntToStr(Number)+".txt"));//  .insert()  (sock,"Res"+IntToStr(Number)+".txt");

          AnsiString filename;
          filename = "Res"+IntToStr(Number)+".txt";

          FILE *F;
          if (!(F = fopen(filename.c_str(),"w")))
          {
              perror("Create File");
              //system("pause");
              //exit();
              break;
          };
          fclose(F);
       }

       for(map<int,AnsiString>::iterator it = clients.begin(); it != clients.end(); it++)

       {
          if(FD_ISSET((*it).first, &ReadSet))
          {
             FILE *F;
             if (!(F = fopen((*it).second.c_str() ,"a")))
             {
                 perror("Create File");
                 //system("pause");
                 //exit();
                 break;
             };


             bytes_read = recv((*it).first, buf, 1024, 0);
             if(bytes_read <= 0)
             {
                 // Соединение разорвано, удаляем сокет из множества
                 closesocket((*it).first);
                 clients.erase((*it).first);
                 continue;
             }
             //записали данные в файл
             fwrite(buf, sizeof(char), strlen(buf), F);

             // Отправляем данные обратно клиенту
             send((*it).first, buf, bytes_read, 0);

             fclose(F);
             delete(F);
             F = NULL;
          }
          printf("\nReceiving the part of file %d is complete.\n",Number);
       }      
    }

    closesocket(sock);
    closesocket(listener);
    //printf("Receiving the file is complete.\n");
    //system("pause");
    _exit(0);

    return 0;
}


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


 




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


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

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