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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> клиент+сервер, Проблемка 
:(
    Опции темы
_par
Дата 25.1.2007, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Недавно начал учить C++ пытаюсь написать программу типа клиент сервер под windows.
Нашел примеры клиента и сервера тут проблема в том , что неполучается откомпилировать TCP сервер. Изпользую Dev-C++.


Клиент

Код


 // Пример простого TCP – эхо сервера

  #include <stdio.h>
  #include <winsock2.h>  // Wincosk2.h должен быть 
          // подключен раньше windows.h!
  #include <windows.h>

  #define MY_PORT    666
           // Порт, который слушает сервер

  // макрос для печати количества активных
  // пользователей 
  #define PRINTNUSERS if (nclients)\
  printf("%d user on-line\n",nclients);\
  else printf("No User on line\n");

  // прототип функции, обслуживающий
  // подключившихся пользователей
  DWORD WINAPI SexToClient(LPVOID client_socket);

  // глобальная переменная – количество
  // активных пользователей 
  int nclients = 0;

  int main(int argc, char* argv[])
  {
    char buff[1024];    // Буфер для различных нужд

    printf("TCP SERVER DEMO\n");

    // Шаг 1 - Инициализация Библиотеки Сокетов
    // Т.к. возвращенная функцией информация
    // не используется ей передается указатель на
    // рабочий буфер, преобразуемый
    // к указателю  на структуру WSADATA.
    // Такой прием позволяет сэкономить одну
    // переменную, однако, буфер должен быть не менее
    // полкилобайта размером (структура WSADATA
    // занимает 400 байт)
    if (WSAStartup(0x0202,(WSADATA *) &buff[0])) 
    {
      // Ошибка!
          printf("Error WSAStartup %d\n",
             WSAGetLastError());
      return -1;
    }

    // Шаг 2 - создание сокета
    SOCKET mysocket;
    // AF_INET     - сокет Интернета
    // SOCK_STREAM  - потоковый сокет (с
    //      установкой соединения)
    // 0      - по умолчанию выбирается TCP протокол
    if ((mysocket=socket(AF_INET,SOCK_STREAM,0))<0)
    {
      // Ошибка!
      printf("Error socket %d\n",WSAGetLastError());
      WSACleanup();
        // Деиницилизация библиотеки Winsock
      return -1;
    }

    // Шаг 3 связывание сокета с локальным адресом
    sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_port=htons(MY_PORT);
             // не забываем о сетевом порядке!!!
    local_addr.sin_addr.s_addr=0;
             // сервер принимает подключения
             // на все IP-адреса

    // вызываем bind для связывания
    if (bind(mysocket,(sockaddr *) &local_addr,
                sizeof(local_addr)))
    {
      // Ошибка
      printf("Error bind %d\n",WSAGetLastError());
      closesocket(mysocket;  // закрываем сокет!
      WSACleanup();
      return -1;
    }

    // Шаг 4 ожидание подключений
    // размер очереди – 0x100
    if (listen(mysocket, 0x100))
    {
      // Ошибка
      printf("Error listen %d\n",WSAGetLastError());
      closesocket(mysocket);
      WSACleanup();
      return -1;
    }

    printf("Ожидание подключений\n");

    // Шаг 5 извлекаем сообщение из очереди
    SOCKET client_socket;    // сокет для клиента
    sockaddr_in client_addr;    // адрес клиента
              // (заполняется системой)

    // функции accept необходимо передать размер
    // структуры
    int client_addr_size=sizeof(client_addr);

    // цикл извлечения запросов на подключение из
    // очереди
    while((client_socket=accept(mysocket, (sockaddr *)
            &client_addr, &client_addr_size)))
    {
      nclients++;      // увеличиваем счетчик
              // подключившихся клиентов

      // пытаемся получить имя хоста
      HOSTENT *hst;
      hst=gethostbyaddr((char *)
          &client_addr.sin_addr.s_addr,4, AF_INET);

      // вывод сведений о клиенте
      printf("+%s [%s] new connect!\n",
      (hst)?hst->h_name:"",
      inet_ntoa(client_addr.sin_addr));
      PRINTNUSERS

      // Вызов нового потока для обслужвания клиента
      // Да, для этого рекомендуется использовать
      // _beginthreadex но, поскольку никаких вызов
      // функций стандартной Си библиотеки поток не
      // делает, можно обойтись и CreateThread
      DWORD thID;
      CreateThread(NULL,NULL,SexToClient,
              &client_socket,NULL,&thID);
    }
    return 0;
  }

  // Эта функция создается в отдельном потоке и
  // обсуживает очередного подключившегося клиента
  // независимо от остальных
  DWORD WINAPI SexToClient(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock=((SOCKET *) client_socket)[0];
    char buff[20*1024];
    #define sHELLO "Hello, Sailor\r\n"

    // отправляем клиенту приветствие 
    send(my_sock,sHELLO,sizeof(sHELLO),0);

    // цикл эхо-сервера: прием строки от клиента и
    // возвращение ее клиенту
    while( (int bytes_recv=
                 recv(my_sock,&buff[0],sizeof(buff),0))
              && bytes_recv !=SOCKET_ERROR)
      send(my_sock,&buff[0],bytes_recv,0);

    // если мы здесь, то произошел выход из цикла по
    // причине возращения функцией recv ошибки –
    // соединение клиентом разорвано
    nclients--; // уменьшаем счетчик активных клиентов
    printf("-disconnect\n"); PRINTNUSERS

    // закрываем сокет
    closesocket(my_sock);
    return 0;
  }




Сервер


Код

// Пример простого TCP клиента
  #include <stdio.h>
  #include <string.h>
  #include <winsock2.h>
  #include <windows.h>


  #define PORT 666
  #define SERVERADDR "127.0.0.1"

  int main(int argc, char* argv[])
  {
    char buff[1024];
    printf("TCP DEMO CLIENT\n");

    // Шаг 1 - инициализация библиотеки Winsock
    if (WSAStartup(0x202,(WSADATA *)&buff[0]))
    {
      printf("WSAStart error %d\n",WSAGetLastError());
      return -1;
    }

    // Шаг 2 - создание сокета
    SOCKET my_sock;
    my_sock=socket(AF_INET,SOCK_STREAM,0);
    if (my_sock < 0)
    {
      printf("Socket() error %d\n",WSAGetLastError());
      return -1;
    }

    // Шаг 3 - установка соединения

    // заполнение структуры sockaddr_in
    // указание адреса и порта сервера
    sockaddr_in dest_addr;
    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(PORT);
    HOSTENT *hst;

    // преобразование IP адреса из символьного в
    // сетевой формат
    if (inet_addr(SERVERADDR)!=INADDR_NONE)
      dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
    else
      // попытка получить IP адрес по доменному
      // имени сервера
      if (hst=gethostbyname(SERVERADDR))
      // hst->h_addr_list содержит не массив адресов,
      // а массив указателей на адреса
      ((unsigned long *)&dest_addr.sin_addr)[0]=
        ((unsigned long **)hst->h_addr_list)[0][0];
      else 
      {
        printf("Invalid address %s\n",SERVERADDR);
        closesocket(my_sock);
        WSACleanup();
        return -1;
      }

    // адрес сервера получен – пытаемся установить
    // соединение 
    if (connect(my_sock,(sockaddr *)&dest_addr,
                sizeof(dest_addr)))
    {
      printf("Connect error %d\n",WSAGetLastError());
      return -1;
    }

    printf("Соединение с %s успешно установлено\n\
    Type quit for quit\n\n",SERVERADDR);

    // Шаг 4 - чтение и передача сообщений
    int nsize;
    while((nsize=recv(my_sock,&buff[0],
                      sizeof(buff)-1,0))
                  !=SOCKET_ERROR)
    {
      // ставим завершающий ноль в конце строки 
      buff[nsize]=0;

      // выводим на экран 
      printf("S=>C:%s",buff);

      // читаем пользовательский ввод с клавиатуры
      printf("S<=C:"); fgets(&buff[0],sizeof(buff)-1,
             stdin);

      // проверка на "quit"
      if (!strcmp(&buff[0],"quit\n"))
      {
        // Корректный выход
        printf("Exit...");
        closesocket(my_sock);
        WSACleanup();
        return 0;
      }

      // передаем строку клиента серверу
      send(my_sock,&buff[0],nsize,0);
    }

    printf("Recv error %d\n",WSAGetLastError());
    closesocket(my_sock);
    WSACleanup();
    return -1;





Подкиньте матерьял по сокетам или примеры по доходчивой реализации такой программы. 
PM MAIL   Вверх
kirjanov
Дата 25.1.2007, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

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



_par
на что компилятор ругается?
PM MAIL   Вверх
_par
Дата 25.1.2007, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот ошибки

ну синтаксис я пытался изправить..


 In function `main': 
 `sockaddr_in' undeclared (first use in this function) 
  (Each undeclared identifier is reported only once 
  for each function it appears in.) 
syntax error before "local_addr" 
`local_addr' undeclared (first use in this function) 
sockaddr' undeclared (first use in this function) 
 syntax error before ')' token 
 syntax error before "client_addr" 
 `client_addr' undeclared (first use in this function) 
 syntax error before ')' token 
 too few arguments to function `accept' 
syntax error before ')' token 
[Warning] passing arg 2 of `CreateThread' makes integer from pointer without a cast 
[Warning] passing arg 5 of `CreateThread' makes integer from pointer without a cast 
  At top level: 
 syntax error before "return" 
 In function `SexToClient': 
 syntax error before "bytes_recv" 
 syntax error before ')' token 
 [Build Error]  [client.o] Error 1 
PM MAIL   Вверх
kirjanov
Дата 26.1.2007, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

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



у тебя компилятор не может найти .h файлы, посмотри, как можно ему указать, где смотреть хидеры.
Последняя ошибка  - что-то со скобками неправильно.
 
PM MAIL   Вверх
witex
Дата 26.1.2007, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Точно, что именно компилятор не находит хидер, или просто н при линкован obj файл! потому что пример занком! Крисса Касперски. Так что у него пример рабочий!
--------------------
Я не волшебник, я только учусь."Шлёпни в Гугл" - Афтор Былов Ю.М. 
PM MAIL   Вверх
_par
Дата 26.1.2007, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



да я всё подгружаю... Осталась последняя ошибка.
[Warning] passing NULL used for non-pointer converting 2 of `void* CreateThread(_SECURITY_ATTRIBUTES*, DWORD, DWORD (*)(void*), void*, DWORD, DWORD*)' 

 ктонибудь знает чё он ругается,как исправить ?
PM MAIL   Вверх
_par
Дата 27.1.2007, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Все разобрался, всем огромное спасибо!!  smile 

Это сообщение отредактировал(а) _par - 27.1.2007, 00:16
PM MAIL   Вверх
Maugle
Дата 6.3.2011, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Интереснро спусть 4 года тут кто нить ответит на вопросы или нет? ))
Жаль автор не описал как он исправил ошибки и не предоставил полностью рабочий текст.
Ввиду этого я вот скопипастил текст проги у меня следующие ошибки:
 
Сервер:
In function `int main(int, char**)': 
passing NULL used for non-pointer converting 2 of `void* CreateThread(_SECURITY_ATTRIBUTES*, DWORD, DWORD (*)(void*), void*, DWORD, DWORD*)' 
passing NULL used for non-pointer converting 5 of `void* CreateThread(_SECURITY_ATTRIBUTES*, DWORD, DWORD (*)(void*), void*, DWORD, DWORD*)' 
In function `DWORD SexToClient(void*)': 
expected primary-expression before "int" 
expected `)' before "int" 
expected `)' before ';' token 

Клиент:
  [Linker error] undefined reference to `WSAStartup@8' 
  [Linker error] undefined reference to `WSAGetLastError@0' 
  [Linker error] undefined reference to `socket@12' 
  [Linker error] undefined reference to `htons@4' 
  [Linker error] undefined reference to `inet_addr@4' 
  [Linker error] undefined reference to `inet_addr@4' 
  [Linker error] undefined reference to `gethostbyname@4' 
  [Linker error] undefined reference to `closesocket@4' 
  [Linker error] undefined reference to `WSACleanup@0' 
  [Linker error] undefined reference to `connect@12' 
ну еще много похожих строк... в конце
  ld returned 1 exit status 

Помогите кто-нить, а то надо лабу сделать (Домино по сети), а препод дает примеры не рабочие из нэта скопированные.
Зарание огромное спасибо!!!
PM MAIL   Вверх
Modul
Дата 7.3.2011, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



либу подключил для WinSock2 ?

#pragma comment(lib, "ws2_32.lib")
--------------------
I'll be back !
PM MAIL   Вверх
Townsmen
Дата 11.9.2011, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Примеры из первого поста как я понял взят с citforum.ru/book/cook/winsock.shtml

Исправил ошибки в коде сервера, может кому надо будет:
Код

// Пример простого TCP – эхо сервера

  #include <stdio.h>
  #include <winsock2.h>  // Wincosk2.h должен быть 
          // подключен раньше windows.h!
  #include <windows.h>
  #pragma comment(lib, "ws2_32.lib") 

  #define MY_PORT    6000
           // Порт, который слушает сервер

  // макрос для печати количества активных
  // пользователей 
  #define PRINTNUSERS if (nclients)\
  printf("%d user on-line\n",nclients);\
  else printf("No User on line\n");

  // прототип функции, обслуживающий
  // подключившихся пользователей
  DWORD WINAPI SexToClient(LPVOID client_socket);

  // глобальная переменная – количество
  // активных пользователей 
  int nclients = 0;

  int main(int argc, char* argv[])
  {
    char buff[1024];    // Буфер для различных нужд

    printf("TCP SERVER DEMO\n");

    // Шаг 1 - Инициализация Библиотеки Сокетов
    // Т.к. возвращенная функцией информация
    // не используется ей передается указатель на
    // рабочий буфер, преобразуемый
    // к указателю  на структуру WSADATA.
    // Такой прием позволяет сэкономить одну
    // переменную, однако, буфер должен быть не менее
    // полкилобайта размером (структура WSADATA
    // занимает 400 байт)
    if (WSAStartup(0x0202,(WSADATA *) &buff[0])) 
    {
      // Ошибка!
          printf("Error WSAStartup %d\n",
             WSAGetLastError());
      return -1;
    }

    // Шаг 2 - создание сокета
    SOCKET mysocket;
    // AF_INET     - сокет Интернета
    // SOCK_STREAM  - потоковый сокет (с
    //      установкой соединения)
    // 0      - по умолчанию выбирается TCP протокол
    if ((mysocket=socket(AF_INET,SOCK_STREAM,0))<0)
    {
      // Ошибка!
      printf("Error socket %d\n",WSAGetLastError());
      WSACleanup();
        // Деиницилизация библиотеки Winsock
      return -1;
    }

    // Шаг 3 связывание сокета с локальным адресом
    sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_port=htons(MY_PORT);
             // не забываем о сетевом порядке!!!
    local_addr.sin_addr.s_addr=0;
             // сервер принимает подключения
             // на все IP-адреса

    // вызываем bind для связывания
    if (bind(mysocket,(sockaddr *) &local_addr,
                sizeof(local_addr)))
    {
      // Ошибка
      printf("Error bind %d\n",WSAGetLastError());
      closesocket(mysocket);  // закрываем сокет!
      WSACleanup();
      return -1;
    }

    // Шаг 4 ожидание подключений
    // размер очереди – 0x100
    if (listen(mysocket, 0x100))
    {
      // Ошибка
      printf("Error listen %d\n",WSAGetLastError());
      closesocket(mysocket);
      WSACleanup();
      return -1;
    }

    printf("Ожидание подключений\n");

    // Шаг 5 извлекаем сообщение из очереди
    SOCKET client_socket;    // сокет для клиента
    sockaddr_in client_addr;    // адрес клиента
              // (заполняется системой)

    // функции accept необходимо передать размер
    // структуры
    int client_addr_size=sizeof(client_addr);

    // цикл извлечения запросов на подключение из
    // очереди
    while((client_socket=accept(mysocket, (sockaddr *)
            &client_addr, &client_addr_size)))
    {
      nclients++;      // увеличиваем счетчик
              // подключившихся клиентов

      // пытаемся получить имя хоста
      HOSTENT *hst;
      hst=gethostbyaddr((char *)
          &client_addr.sin_addr.s_addr,4, AF_INET);

      // вывод сведений о клиенте
      printf("+%s [%s] new connect!\n",
      (hst)?hst->h_name:"",
      inet_ntoa(client_addr.sin_addr));
      PRINTNUSERS

      // Вызов нового потока для обслужвания клиента
      // Да, для этого рекомендуется использовать
      // _beginthreadex но, поскольку никаких вызов
      // функций стандартной Си библиотеки поток не
      // делает, можно обойтись и CreateThread
      DWORD thID;
      CreateThread(NULL,NULL,SexToClient,
              &client_socket,NULL,&thID);
    }
    return 0;
  }

  // Эта функция создается в отдельном потоке и
  // обсуживает очередного подключившегося клиента
  // независимо от остальных
  DWORD WINAPI SexToClient(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock=((SOCKET *) client_socket)[0];
    char buff[20*1024];
    #define sHELLO "Hello, Sailor\r\n"

    // отправляем клиенту приветствие 
    send(my_sock,sHELLO,sizeof(sHELLO),0);

    // цикл эхо-сервера: прием строки от клиента и
    // возвращение ее клиенту
    while(int bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0)){
      send(my_sock,&buff[0],bytes_recv,0);
      }
    // если мы здесь, то произошел выход из цикла по
    // причине возращения функцией recv ошибки –
    // соединение клиентом разорвано
    nclients--; // уменьшаем счетчик активных клиентов
    printf("-disconnect\n"); PRINTNUSERS

    // закрываем сокет
    closesocket(my_sock);
    return 0;
  }


Это сообщение отредактировал(а) Townsmen - 11.9.2011, 14:57
PM MAIL   Вверх
bazilio
  Дата 10.4.2012, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Возник вопрос по работе с winsock. Использую пример из книги Касперски К. который выложен выложен в первом посте, поэтому и решил написать в этой теме.
В коде сервера 
Код

if (listen(mysocket, 0x100))
    {
      // Ошибка
      printf("Error listen %d\n",WSAGetLastError());
      closesocket(mysocket);
      WSACleanup();
      return -1;
    }

переводим сервер в режим ожидания функцией listen, параметры - дескриптор сокета и размер очереди.
Проблема в том, что мне ни как не удается ограничить кол-во подключающихся клиентов. В примере, как я понимаю, размер очереди указан в шестнадцатеричном представлении, пробовал ставить просто "1" - не помогает, может кто подскажет в чем дело?
PM MAIL   Вверх
Олег2005
Дата 11.4.2012, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Функция listen() описывается так:
int listen(int sd, int backlog);
где sd – дескриптор сокета, backlog – задает максимальный размер очереди для приходящих запросов соединения (то есть, сколько запросов может быть принято на обслуживание без потерь, обычно этот параметр равен 5). При переполнении очереди будет послано сообщение об ошибке. До сих пор рекомендуемая максимальная длина очереди для многих реализаций равна пяти. Если в настройках стека попытаться указать большее число, то можно в зависимости от реализации или получить сообщение об ошибке, или нет.
На самом деле во многих TCP-модулях различных ОС истинное значение длины очереди буфера для приема входящих соединений расчитывается по формуле: 
backlog * 3 / 2 + 1
и listen(sd, 0) разрешит принять одно соединение,  listen (sd, 5)  - 8. 
Система Solaris интерпретирует listen(sd,0) как запрет на прием заявок, BSD интерпретирует как (0*3/2+1 = 1) – одно соединение. Отрицательное значение backlog практически во всех реализациях трактуется как 0.
Если очередь при поступлении нового запроса окажется переполненной, то модуль TCP не ответит посылкой сегмента RST, а просто отвергнет его, и программа-клиент сможет еще несколько раз слать свой SYN-сегмент (см. описание внутреннего таймаута функции connect()). Если необходимо при работающем сервере послать именно RST, надо просто закрыть слушающий сокет.
Примечание
Современные стеки TCP/IP позволяют устанавливать значение backlog на несколько порядков выше. Формула расчета полной очереди буферов  тоже может меняться.

PM MAIL WWW MSN   Вверх
bazilio
Дата 11.4.2012, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

Если очередь при поступлении нового запроса окажется переполненной, то модуль TCP не ответит посылкой сегмента RST, а просто отвергнет его, и программа-клиент сможет еще несколько раз слать свой SYN-сегмент (см. описание внутреннего таймаута функции connect()).

Как я понимаю, при переполненной очереди, клиент будет отправлять SYN-сегмент пока не закончится таймаут. Но если очередь переполнена, то сервер не должен отвечать клиенту, а в этой программе клиенты свободно подключаются при любых значениях backlog.
Цитата

Если необходимо при работающем сервере послать именно RST, надо просто закрыть слушающий сокет.

Но если закрыть сокет, то сервер больше вообще не будет принимать запросы, а мне необходимо, что бы сервер обслуживал ограниченное количество клиентов, и при отключении их, мог принять других до заполнения очереди.
Возможно ли это реализовать используя данный пример клиент-сервера?
PM MAIL   Вверх
Олег2005
Дата 13.4.2012, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Цитата(bazilio @  11.4.2012,  09:57 Найти цитируемый пост)
а в этой программе клиенты свободно подключаются при любых значениях backlog.

Несколько вопросов.
1. Какая структура сети - т.е. расположены ли все клиенты - и сервер - в одной локалке или на одной машине
2. С какой скоростью(иначе не придумать названия) клиенты бомбят сервер?

Потому как есть вариант - особенно при моделировании - что сервер успевает быстро обработать заявку на соединение - и потому очередь не переполняется.

Добавлено через 6 минут и 14 секунд
Цитата(bazilio @  11.4.2012,  09:57 Найти цитируемый пост)
необходимо, что бы сервер обслуживал ограниченное количество клиентов, и при отключении их, мог принять других до заполнения очереди.

Сделать это наверно не совсем просто.
Я бы предложил "кривой" вариант - использовать простой счетчик подключений (сколько прошло accept) При этом надо использовать
SOCKET WSAAPI  WSAAccept (
IN    SOCKET            sd, 
OUT    struct sockaddr FAR *    addr,
IN OUT    LPINT                addrlen, 
IN    LPCONDITIONPROC        lpfnCondition, 
IN    DWORD                dwCallbackData);
Здесь:
·    addr - необязательный указатель на буфер (структуру), где должен храниться адрес подключаемого объекта; формат адреса определяется типом протокола, заданным при создании сокета;
·    addrlen - необязательный указатель на целую переменную, которая определяет длину аргумента addr;
·    lpfnCondition - адрес необязательный процедуры, которая на основе анализа некоторых условий (например, нежелательный IP-адрес) возвращает CF_ACCEPT для приема, CF_REJECT для отказа обслуживания запроса или CF_DEFER для отложенного анализа. На основе анализа возврата WSAAccept() принимает решение о дальнейшей обработке, или о создании группы сокетов, или подключает сокет к уже существующей группе. Например, надо отказаться от обслуживания запроса. Функция анализа возвращает CF_REJECT и WSAAccept() в свою очередь возвращает INVALID_SOCKET с кодом ошибки WSAECONNREFUSED. Режим вызова процедуры, адресованной lpfnCondition, осуществляется  установкой опции прослушивающего сокета SO_CONDITIONAL_ACCEPT (тип - BOOL). Использование этого режима снижает нагрузку на сеть и повышает устойчивость сервера против атак.
·    DwCallbackData - параметр, возвращаемый приложению. Этот параметр не интерпретируется WinSock.

PM MAIL WWW MSN   Вверх
bazilio
  Дата 13.4.2012, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Пробовал различные варианты - на одной машине; клиент  из локалки; клиент из внешней сети;
Со скоростью не эксперементировал - клиент подключается и ожидает ввода данных что бы их отправить серверу, т.е. получается что:
Цитата(Олег2005 @ 13.4.2012,  10:53)
сервер успевает быстро обработать заявку на соединение - и потому очередь не переполняется.

Вообщем, backlog ограничивает количество клиентов одновременно обращающихся к серверу, я же думал, что можно будет ограничить количество подключений.
Вариант интересный, буду пробовать. Еще есть идея использовать счетчик клиентов из примера:
Код

#define PRINTNUSERS if (nclients)\
  printf("%d user on-line\n",nclients);\
  else printf("No User on line\n");

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


 




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


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

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