Одновременное клиент-соединение со 100 компьютерами
От: Anokhov Россия  
Дата: 02.11.05 15:02
Оценка:
Нужно в один момент получить с более, чем 100 машин некоторые данные от работающих там клиентских частей программы, собрать статистику с клиентов. Потом в серверной части все эти данные собрать в один текстовый файлик и сохранить его.

Подскажите как лучше реализовать такую задачу с сокетами? Т е мне в моей серверной части программы надо одновременно поднять 100 клиентских сокетов, каждый из которых подключится к своей машине и скачает данные с нее.

Вариант с fork() не очень подходит, т к если в один момент будет работать 3 серверных программы, это уже будет огромное количество процессов.
Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&


Подскажите куда копать и что полезного почитать.

Спасибо.
Re: Одновременное клиент-соединение со 100 компьютерами
От: Аноним  
Дата: 02.11.05 15:08
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Вариант с fork() не очень подходит, т к если в один момент будет работать 3 серверных программы, это уже будет огромное количество процессов.

A>Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&

303 процесса это не много. Можно еще с потоками..
Re: Одновременное клиент-соединение со 100 компьютерами
От: Аноним  
Дата: 02.11.05 15:56
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Нужно в один момент получить с более, чем 100 машин некоторые данные от работающих там клиентских частей программы, собрать статистику с клиентов. Потом в серверной части все эти данные собрать в один текстовый файлик и сохранить его.


A>Подскажите как лучше реализовать такую задачу с сокетами? Т е мне в моей серверной части программы надо одновременно поднять 100 клиентских сокетов, каждый из которых подключится к своей машине и скачает данные с нее.


A>Вариант с fork() не очень подходит, т к если в один момент будет работать 3 серверных программы, это уже будет огромное количество процессов.

Можно совместить fork() с потоками — напр. 20 процессов с 5 потоками (+1 главный) в каждом.

A>Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&

Для этого в select выставляется таймаут.

A>Подскажите куда копать и что полезного почитать.

не буду оригинальным — Стивенс "разработка сетевых приложений"
Re: Одновременное клиент-соединение со 100 компьютерами
От: Kemm  
Дата: 02.11.05 20:38
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&


fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK)?
Re: Одновременное клиент-соединение со 100 компьютерами
От: srggal Украина  
Дата: 03.11.05 10:32
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Нужно в один момент получить с более, чем 100 машин некоторые данные от работающих там клиентских частей программы, собрать статистику с клиентов. Потом в серверной части все эти данные собрать в один текстовый файлик и сохранить его.


A>Подскажите как лучше реализовать такую задачу с сокетами? Т е мне в моей серверной части программы надо одновременно поднять 100 клиентских сокетов, каждый из которых подключится к своей машине и скачает данные с нее.


A>Вариант с fork() не очень подходит, т к если в один момент будет работать 3 серверных программы, это уже будет огромное количество процессов.

A>Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&


A>Подскажите куда копать и что полезного почитать.


ИМХО Пулл рабочих потоков 4-8, но не 100
читают данные с клиента, помещают в очередь, основной поток вычитывает данные из очереди осчитывает и пишет в файл.

очередь — может бытьсамописной, можно ACE_MessageQueue ( точно не помню ).
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Одновременное клиент-соединение со 100 компьютерами
От: lyk  
Дата: 03.11.05 11:11
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Нужно в один момент получить с более, чем 100 машин некоторые данные от работающих там клиентских частей программы, собрать статистику с клиентов. Потом в серверной части все эти данные собрать в один текстовый файлик и сохранить его.


A>Подскажите как лучше реализовать такую задачу с сокетами? Т е мне в моей серверной части программы надо одновременно поднять 100 клиентских сокетов, каждый из которых подключится к своей машине и скачает данные с нее.


A>Вариант с fork() не очень подходит, т к если в один момент будет работать 3 серверных программы, это уже будет огромное количество процессов.

A>Вариант с Select() — не могу понять, как организовать одновременно большое количество коннектов к удаленным машинам, так чтобы программа не "засыпала" на время попытки соединения (а вдруг удаленная машина не работает), как после этого работать с успешными коннектами в том же режиме без "подвисания программы"&


A>Подскажите куда копать и что полезного почитать.


A>Спасибо.


По-моему по тем условиям надо выбраться из-за деревьев и увидеть лес, т.е. проблему: надо послать на кучу клиентов запросы и получить ответы. Я бы сделал проще — по UDP шлется широковещательный запрос (можно подряд сразу 2 с одним идентификатором). Все работающие клиенты отвечают по TCP. Если по алгоритму — не все ответили — опять пара UDP с тем же идентификатором — ответившие на тот же идентификатор большее не должны реагировать. Городить список клиентов, которые должны молчать, в запросе по-моему нецелесообразно. Ограничения — используются шлюзы, не пропускающие пироковещаловок и др.
Re: Одновременное клиент-соединение со 100 компьютерами
От: _kostet_ Россия  
Дата: 03.11.05 11:56
Оценка: +1
Anokhov wrote:
>
> Нужно в один момент получить с более, чем 100 машин некоторые данные от
> работающих там клиентских частей программы, собрать статистику с
> клиентов. Потом в серверной части все эти данные собрать в один
> текстовый файлик и сохранить его.
>
> Подскажите как лучше реализовать такую задачу с сокетами? Т е мне в моей
> серверной части программы надо одновременно поднять 100 клиентских
> сокетов, каждый из которых подключится к своей машине и скачает данные с
> нее.
>
> Вариант с fork() не очень подходит, т к если в один момент будет
> работать 3 серверных программы, это уже будет огромное количество процессов.
> Вариант с Select() — не могу понять, как организовать одновременно
> большое количество коннектов к удаленным машинам, так чтобы программа не
> "засыпала" на время попытки соединения (а вдруг удаленная машина не
> работает), как после этого работать с успешными коннектами в том же
> режиме без "подвисания программы"&
>
>
> Подскажите куда копать и что полезного почитать.
>

Все должно прекрасно работать на одном потоке. Все что нужно для того чтобы
выполнить эту задачу это: главный цикл, неблокирующие сокеты, и select (а лучше
в твоем случае poll) с таймаутом == 0. Вообще 100 соединений это не так много.
Если еще не понятно, то пиши могу пояснить.
Posted via RSDN NNTP Server 2.0 beta
Re[2]: Одновременное клиент-соединение со 100 компьютерами
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.11.05 13:30
Оценка:
Здравствуйте, srggal, Вы писали:

A>>Подскажите куда копать и что полезного почитать.


S>ИМХО Пулл рабочих потоков 4-8, но не 100

S>читают данные с клиента, помещают в очередь, основной поток вычитывает данные из очереди осчитывает и пишет в файл.

Раз уж упомянули ACE, то можно ACE_Reactor и ACE_Task.

S>очередь — может бытьсамописной, можно ACE_MessageQueue ( точно не помню ).


Да, есть там такое.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Одновременное клиент-соединение со 100 компьютерами
От: srggal Украина  
Дата: 03.11.05 13:32
Оценка: +1 :)
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, srggal, Вы писали:


A>>>Подскажите куда копать и что полезного почитать.


S>>ИМХО Пулл рабочих потоков 4-8, но не 100

S>>читают данные с клиента, помещают в очередь, основной поток вычитывает данные из очереди осчитывает и пишет в файл.

E>Раз уж упомянули ACE, то можно ACE_Reactor и ACE_Task.


Можно, просто это более высокоуровневое, разбираться на 20 минут дольше
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Одновременное клиент-соединение со 100 компьютерами
От: Anokhov Россия  
Дата: 03.11.05 17:32
Оценка:
>Все должно прекрасно работать на одном потоке. Все что нужно для того чтобы
>выполнить эту задачу это: главный цикл, неблокирующие сокеты, и select (а лучше
>в твоем случае poll) с таймаутом == 0. Вообще 100 соединений это не так много.
>Если еще не понятно, то пиши могу пояснить.

Не понятно Почитал отзывы — народ глумится... UDP и прочие супер-навороты ИМХО не на моей достаточно простой задаче совсем лишнее дело.

Т к реализация с Select сама по себе запутанная, я не могу придумать, в каких местах правильнее вызывать fcntl. Ведь мне надо запустить 100 сокетов на соединение (неблокирующих), потом отлавливать успешные коннекты и работать с ними в том же незаблокированном режиме. Данных не много приходит, потому я их легко могу собрать все в одну текстовую переменную и записать в файл уже по окончанию всего процесса получения данных, проблемы с обращением к файлу не учитываем.

fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK)?

идея верна, но как мне отлавливать например ошибки, возникшие при коннекте?


Мне бы небольшой элементарный пример реализации...
Re[3]: Одновременное клиент-соединение со 100 компьютерами
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.11.05 18:04
Оценка:
Anokhov wrote:
>
> Т к реализация с Select сама по себе запутанная, я не могу придумать, в
> каких местах правильнее вызывать fcntl. Ведь мне надо запустить 100
> сокетов на соединение (неблокирующих), потом отлавливать успешные
> коннекты и работать с ними в том же незаблокированном режиме. Данных не
> много приходит, потому я их легко могу собрать все в одну текстовую
> переменную и записать в файл уже по окончанию всего процесса получения
> данных, проблемы с обращением к файлу не учитываем.

Все это достаточно просто, на самом деле.

select позволяет ждать одновременно готовности нескольких файловых
дескрипторов (кстати, юниксовский селект работает не только с сокетами,
но и с pipe'ами и characted devices).

Select'у надо передать 3 множества дескрипторов — те, которые тебе
интересны 1) на чтение 2) на запись 3) на предмет возникновения
исключительных ситуаций (exceptions). Опционально так же указывается
timeout.

Если select проснулся не из-за таймаута, он вернет некоторое количество
дескрипторов.

Понимать выданные им значения следует так:
1. Если дескриптор "готов на чтение", это значит, что в нем что-то
изменилось, имеющее отношение к чтению. Это не значит, что read
гарантированно вернет какие-либо данные. Это лишь значит, что стоит
попробовать почитать — read может вернуть данные, ошибку, или признак
конца файла (закрытия соединения). Можно сформулировать и по-другому,
готовность дескриптора на чтение означает, что read не заблокируется и
не вернет EWOULDBLOCK.
2. То же верно в отношении write.
3. Про exceptions пока промолчим

На всякий случай дескрипторы лучше перевести в неблокирующийся режим.
Это избавит тебя от неожиданных блокировок. Это делается fcntl'ом, и это
можно сделать сразу, как только ты создал дескриптор.

Теперь в отношении connect, listen и accept.

Сокет, на который сказали connect, становится готовым на запись, когда
connect чем-нибудь завершился.

Если connect завершится удачно, сокет сразу станет готовым на запись, но
на чтение он станет готовым не раньше, чем придут какие-то данные. Это
логично: посылать данные можно сразу после соединения, принимать — не
раньше, чем их пришлет другая сторона.

Если connect завершился неудачно, сокет станет готовым сразу на чтение и
на запись. О самой ошибке ты узнаешь, когда попробуешь что-нибудь оттуда
почитать или туда пописать — read/write вернет ошибку. После этого сокет
можно только закрыть.

Сокет, на который сказали listen, становится готовым на чтение, когда к
нему кто-то приконнектился. Читать оттуда при этом не стоит, а стоит
сказать accept. accept как-бы вычитывает оттуда новый сокет.

Сокет, полученный от accept'а ничем не отличается от любого другого
нормального подсоединенного сокета — его точно так же можно "няньчить"
select'ом,

И наконец, одни маленькие грабли Первый параметр select'а это не
количество файловых дескрипторов, а номер самого большого из них, плюс
один. Т.е., например, если ты используешь дескрипторы 4, 5 и 7, то
первый параметр селекта будет 8, и при этом не важно, как эти
дескрипторы разложены между тремя fd_set'ами.
Posted via RSDN NNTP Server 1.9
Re[4]: Одновременное клиент-соединение со 100 компьютерами
От: Anokhov Россия  
Дата: 03.11.05 18:19
Оценка:
Pzz>Select'у надо передать 3 множества дескрипторов — те, которые тебе
Pzz>интересны 1) на чтение 2) на запись 3) на предмет возникновения
Pzz>исключительных ситуаций (exceptions). Опционально так же указывается
Pzz>timeout.

Спасибо за расширенный ответ Как с Select'ом работать — это я разобрался. Очень подробная статья есть в разделе "Статьи" (http://www.rsdn.ru/article/unix/sockets.xml
Автор(ы): Александр Шаргин
Дата: 16.05.2001
)


Но у меня затык именно в ожиданнии успешного коннекта. Следуюя логике получается, что мы должны делать как select следящий за Connect, так и Select следящий за уже работающим (принимающим) сокетом. Получается уже какая-то вложенная схема, т к пока один сокет еще соединяется только (ну мало ли, там коннект отстойный у компьютера) то другой уже может успеть все передать...


Или может мне в одни множетсва засовывать одновременно и дескрипторы Connect и дескрипторы собственно коннектов, по которым данные идут? Как тогда их отделять друг от друга по типам?
Re[5]: Одновременное клиент-соединение со 100 компьютерами
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.11.05 18:33
Оценка:
Anokhov wrote:
>
> Но у меня затык именно в ожиданнии успешного коннекта. Следуюя логике
> получается, что мы должны делать как select следящий за Connect, так и
> Select следящий за уже работающим (принимающим) сокетом. Получается уже
> какая-то вложенная схема, т к пока один сокет еще соединяется только (ну
> мало ли, там коннект отстойный у компьютера) то другой уже может успеть
> все передать...
>
> Или может мне в одни множетсва засовывать одновременно и дескрипторы
> Connect и дескрипторы собственно коннектов, по которым данные идут? Как
> тогда их отделять друг от друга по типам?

Да, именно так — засовывать одновременно. Чтобы различать, что с каким
сокетом делать, надо отдельно от сокета хранить структурку, в которой
лежит вся интересная информация, и находить эту структурку по номеру сокета.
Posted via RSDN NNTP Server 1.9
Re[6]: Одновременное клиент-соединение со 100 компьютерами
От: Anokhov Россия  
Дата: 04.11.05 12:52
Оценка:
>Да, именно так — засовывать одновременно. Чтобы различать, что с каким
>сокетом делать, надо отдельно от сокета хранить структурку, в которой
>лежит вся интересная информация, и находить эту структурку по номеру сокета.


Кому не лень, гляньте Логика вроде верная, и программа частично работает. Т е соединение устанавливается, данные удаленному серверу отправляются. Точно проверено, что удаленный сервер эти данные получает и отправляет ответ...

но почему-то ответ этот не принимается. Т е у меня сейчас просто отправляются данные, потом программулина висит на Select 10 секунд и вылетает по таймауту селекта.

Вчем ошибка?

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>

#include <algorithm>
#include <set>
using namespace std;

int main()
{
    set<int> clients; //Множесто с номерами клиентов (сокетов), нужно для высчитывания максимального sock
    clients.clear();

    int sock; //Сокет для конекта

    //Множества, которые мы засовываем в Select
    fd_set readset;  //Для чтения
    FD_ZERO(&readset);
    fd_set writeset;  //Для записи
    FD_ZERO(&writeset);

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

    for (int i = 0; i < 5; i++)  //Цикл создания 5 коннектов
    {
      printf("creating clients...\n");

      sock = socket(AF_INET, SOCK_STREAM, 0); //Выделяем сокет
      if(sock < 0) continue;

      struct sockaddr_in addr; //Структура с адресом для коннекта
      addr.sin_family = AF_INET;
      addr.sin_port = htons(8080); // порт
      addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //Адрес для конекта

      if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) //Пытаемся подключиться
      {
        printf("not connected\n");
        continue;
      }

      fcntl(sock, F_SETFL, O_NONBLOCK); //Переводим его в неблокирующий вид

      clients.insert(sock);   //В клиенты его...
      //Запихиваем в множества сокет, чтобы его потом отслеживать
      FD_SET(sock, &readset);
      FD_SET(sock, &writeset);
    }


    //А теперь ждем, пока все клиенты отработают
    for(int j=0; !clients.empty() && j<=50; j++)
    {
      printf("In <for>...\n");

      int mx = *max_element(clients.begin(), clients.end()); //Вычисляем максимальный номер sock для Select

      // Ждём события в одном из сокетов
      if(select(mx+1, &readset, &writeset, NULL, &timeout) <= 0)
      {
        printf("Happy end.\n");
        exit(3);
      }


      //Готовые к записи (подключенные сокеты)
      for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
      {
        if(FD_ISSET(*it, &writeset))
        {
          int bytes_send = send(*it, "Hi!", 4, 0); //Отправляем ему наше скромное послание ;)

          //Ошибка - ничего не получилось отправить
          if (bytes_send <= 0) {
            printf("Nothing sent...\n");
            close(*it); //Закрываем
            clients.erase(*it); //Удаляем из клиентов
            FD_CLR(*it, &writeset); //Больше не слушаем
            continue;
          }
          else
          {
            printf("Successfully sent...\n");
            FD_CLR(*it, &writeset); //Удаляем из множества, т к больше ничего отправлять не будем
          }
        }
      }



      //Проверяем, какие сокеты готовы к чтению (т е удаленная машина нам фигню какую-то отправила)
      for(set<int>::iterator it = clients.begin(); it != clients.end(); it++)
      {
        if(FD_ISSET(*it, &readset))
        {
          char buf[1024];
          int bytes_read = recv(*it, buf, 1024, 0);

          printf(buf); //выводим, что получили

          close(*it); //Закрываем
            clients.erase(*it); //Удаляем из клиентов
            FD_CLR(*it, &readset); //Удаляем из прослушиваемых
            continue;
        }
      }



    }

    //Когда у нас кончились все клиенты, т е мы их всех обработали, получается КОНЕЦ :)
    printf("End of file\n");
    return 0;
}
Re[7]: Одновременное клиент-соединение со 100 компьютерами
От: Vladimir D Belousov Россия  
Дата: 05.11.05 18:52
Оценка:
Здравствуйте, Anokhov, Вы писали:

A>Кому не лень, гляньте Логика вроде верная, и программа частично работает. Т е соединение устанавливается, данные удаленному серверу отправляются. Точно проверено, что удаленный сервер эти данные получает и отправляет ответ...


A>но почему-то ответ этот не принимается. Т е у меня сейчас просто отправляются данные, потом программулина висит на Select 10 секунд и вылетает по таймауту селекта.


А что у вас на 8080 висит?
Кроме того, сделайте так:
int s;
AGAIN:
   if((s = select(mx+1, &readset, &writeset, NULL, &timeout)) <= 0) {
      if(errno = EINTR){
          printf("Interrupted call.\n");
          goto AGAIN;
      }
      if(s == 0){
          printf("Timeout\n");
      }else{
          printf("Errno: %d\n", errno);
      }
      exit(3);
   }

просто, чтобы удостовериться, что это именно оно.

Да, и еще. То, что connect() происходит в блокирующем режиме — так и задумано?
Сделайте его неблокируемым ДО connect(), в этом случае вы получите EINPROGRESS и точно так же ждите его в select-е (если соединение будет успешным, дескриптор станет готовым для записи, а в случае ошибки — и для записи, и для чтения).
--
Спасибо
Re[8]: Одновременное клиент-соединение со 100 компьютерами
От: Kemm  
Дата: 05.11.05 18:55
Оценка:
Здравствуйте, Vladimir D Belousov, Вы писали:

VDB>А что у вас на 8080 висит?

VDB>Кроме того, сделайте так:
VDB>
VDB>int s;
VDB>AGAIN:
VDB>   if((s = select(mx+1, &readset, &writeset, NULL, &timeout)) <= 0) {
VDB>      if(errno = EINTR){
VDB>          printf("Interrupted call.\n");
VDB>          goto AGAIN;
VDB>      }
VDB>      if(s == 0){
VDB>          printf("Timeout\n");
VDB>      }else{
VDB>          printf("Errno: %d\n", errno);
VDB>      }
VDB>      exit(3);
VDB>   }
VDB>

VDB>просто, чтобы удостовериться, что это именно оно.

Нет, goto штука, безусловно, полезная, но тут все же лучше нормальный while(). 8)))
Re[9]: Одновременное клиент-соединение со 100 компьютерами
От: Vladimir D Belousov Россия  
Дата: 05.11.05 18:59
Оценка:
Здравствуйте, Kemm, Вы писали:

K>Здравствуйте, Vladimir D Belousov, Вы писали:


VDB>>А что у вас на 8080 висит?

VDB>>Кроме того, сделайте так:
VDB>>
VDB>>int s;
VDB>>AGAIN:
VDB>>   if((s = select(mx+1, &readset, &writeset, NULL, &timeout)) <= 0) {
VDB>>      if(errno = EINTR){
VDB>>          printf("Interrupted call.\n");
VDB>>          goto AGAIN;
VDB>>      }
VDB>>      if(s == 0){
VDB>>          printf("Timeout\n");
VDB>>      }else{
VDB>>          printf("Errno: %d\n", errno);
VDB>>      }
VDB>>      exit(3);
VDB>>   }
VDB>>

VDB>>просто, чтобы удостовериться, что это именно оно.

K>Нет, goto штука, безусловно, полезная, но тут все же лучше нормальный while(). 8)))


Не буду спорить, хотя замечу — не jongjump же
В этом случае да, лучше while, а для отладки — удобно просто (главное — меру знать)
--
Спасибо
Re[3]: Одновременное клиент-соединение со 100 компьютерами
От: _kostet_ Россия  
Дата: 06.11.05 12:20
Оценка:
UAnokhov wrote:
>
> Не понятно Почитал отзывы — народ глумится... UDP и прочие
> супер-навороты ИМХО не на моей достаточно простой задаче совсем лишнее дело.
>
> Т к реализация с Select сама по себе запутанная, я не могу придумать, в
> каких местах правильнее вызывать fcntl. Ведь мне надо запустить 100
> сокетов на соединение (неблокирующих), потом отлавливать успешные
> коннекты и работать с ними в том же незаблокированном режиме. Данных не
> много приходит, потому я их легко могу собрать все в одну текстовую
> переменную и записать в файл уже по окончанию всего процесса получения
> данных, проблемы с обращением к файлу не учитываем.
>
> fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) |
> O_NONBLOCK)?
>
> идея верна, но как мне отлавливать например ошибки, возникшие при коннекте?
>

Про UDP я и не говорил.
fcnt ты вызываешь после того как создашь сокет.
Сокеты у тебя не блокирующие, и это означает что connect у тебя
отработает моментально. После того как ты сделал connect для каждого из
сокетов, ты должен в цикле смотреть активность на сокетах. Т.е. ты
добавляешь все сокеты в fd_set и вызываешь select (для всех сокетов
сразу) с нулевым таймаутом. Кстати сокеты лучше хранить в структуре,
потому как помимо fd сокета, тебе нужно знать в каком состоянии он
находится. Итак, select тебе вернет сокеты (надеюсь ты знаешь как их
вытаскивать) для которых есть активность на запись (сокет после удачного
коннекта получает активность на запись). Ты их смотришь и меняешь статус
у них на connected (например). Цикл в котором ты будешь вызывать select,
так называемый главный цикл, должен тратить на итерацию минимум времени,
а так как у нас полностью асинхронная модель, то он будет крутиться и
обрабатывать коннекции до тех пор пока внешние сигналы не вызовут его
зевершения. Тебе легко отсчитывать время в течении которого мы пытаемся
установить соединение для каждого сокета. Время это опять же можно
хранить в структуре сокета. Время коннекта превышено и коннекта до сих
пор нет ? connect timeout и пошел на фиг, закрыл его и зыбыл. Но самый
прикол в том что активность установленных соединения ты тоже должен
отслежывать в этом же цикле ! Если у тебя возникает активность на чтение
и сокет уже в состоянии connected это означает, что пришли данные и надо
читать.

Извини, спешил, и может что упустил. Если надо еще подробнее то кричи.
Да кстати, может в твоем случае лучше начать не с select'а, а с poll'а.
Мне кажеться реализация с ним для тебя покажется более прозрачной и
понятной.

man poll
Posted via RSDN NNTP Server 2.0 beta
Re[8]: Одновременное клиент-соединение со 100 компьютерами
От: Anokhov Россия  
Дата: 06.11.05 15:46
Оценка:
VDB>А что у вас на 8080 висит?

Тестовый эхо-клиент...

VDB>Да, и еще. То, что connect() происходит в блокирующем режиме — так и задумано?


Не совсем но, насколько я понимаю, fcntl надо вызывать сразу после connect?


В общем мой вариант, описанный выше, работает, с одной доработкой. Я &readset очищаю и заполняю каждый раз в цикле перед вызовом Select заново. Нигде в документации я не смог найти, почему так. Но по тестам у меня получилось, что Select после того, как срабатывает, очищает &readset? Или может он удаляет из него все дескрипторы, которые не сработали? Подскажите, что в действительности происходит?
Re[9]: Одновременное клиент-соединение со 100 компьютерами
От: Kemm  
Дата: 06.11.05 15:55
Оценка:
Здравствуйте, Anokhov, Вы писали:

VDB>>Да, и еще. То, что connect() происходит в блокирующем режиме — так и задумано?

A>Не совсем но, насколько я понимаю, fcntl надо вызывать сразу после connect?

А как тогда connect() может не заблокироваться, если сокет не переведен в неблокирующий режим? 8)) Как раз наоборот -- сразу после создания клиентского сокета.

A>В общем мой вариант, описанный выше, работает, с одной доработкой. Я &readset очищаю и заполняю каждый раз в цикле перед вызовом Select заново. Нигде в документации я не смог найти, почему так. Но по тестам у меня получилось, что Select после того, как срабатывает, очищает &readset? Или может он удаляет из него все дескрипторы, которые не сработали? Подскажите, что в действительности происходит?


Кстати, да. Я не обратил внимания на работу с fd_set. В мане же написано:
On return, select() replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation.

Иначе бы FD_ISSET() и не работал бы. 8)) Поэтому обычно все обнуляется и заполняется заново.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.