Как select () монитор сокетов? - PullRequest
       4

Как select () монитор сокетов?

2 голосов
/ 08 декабря 2011

Как описано в Руководство Beej по сетевому программированию , select () отслеживает набор файловых дескрипторов для чтения (используя recv()), набор файловых дескрипторов для записи (используя send()) ипоследний, я не знаю.Когда сокет сервера получает сообщение от клиентских сокетов, набор read_fds будет изменен и select() вернется из состояния блокировки.То же самое для отправки сообщения в клиентские сокеты.Например:

for(;;) {
        read_fds = master; // copy it
        if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(4);
        }
//the rest is code for processing ready socket

Я полагаю, что набор read_fds будет содержать единственный дескриптор готового сокета на данный момент (остальные удалены), а дескриптор готового сокета - это новый подключенный сокет или сообщение, отправленное сподключенная розетка.Правильно ли мое понимание?

Кажется, готовый сокет должен обрабатываться один за другим.Когда я попытался запустить его на gdb, чтобы понять поведение, когда программа обрабатывала готовый сокет (код после возврата select()), я попытался отправить некоторое сообщение и подключиться к серверу некоторыми новыми клиентами.Как он может распознать новых клиентов или вновь отправленное сообщение, даже если select() не вызывается?

Ответы [ 2 ]

3 голосов
/ 08 декабря 2011

Как описано в Beej's Guide по сетевому программированию, select () отслеживает набор файловых дескрипторов для чтения (используя recv ()), набор файловых дескрипторов для записи (используя send ())

Да

и последний, я не знаю.

Последнее больше не имеет никакого полезного значения.

Я полагаю, что набор read_fds будет содержать единственный дескриптор готового сокета на данный момент (остальные удалены), а дескриптор готового сокета - это новый подключенный сокет или сообщение, отправленное с подключенного сокета. Правильно ли мое понимание?

Это верно.

Кажется, готовый сокет должен обрабатываться один за другим. Когда я попытался запустить его на gdb, чтобы понять поведение, когда программа обрабатывала готовый сокет (код после select () return), я попытался отправить некоторое сообщение и подключиться к серверу несколькими новыми клиентами. Как он может распознать новых клиентов или вновь отправленное сообщение, даже если select () не вызывается?

Обычно, когда вы создаете цикл опроса, такой как этот, вы добавляете новые сокеты в цикл. То есть вы добавите их в соответствующие наборы fd_sets перед следующим вызовом для выбора.

Когда новый сокет станет доступным для записи, вы будете send на нем.

2 голосов
/ 08 декабря 2011

Когда вы имеете дело с несколькими сокетами, которые могут потенциально блокировать (в вашем случае чтение сокетов), вам необходимо определить, в каких сокетах есть данные, ожидающие чтения. Вы можете сделать это, вызвав select () и добавив сокеты в ваш read_set.

Для вашего сокета прослушивания, если вы вызываете accept () и нет ожидающего соединения, тогда ваш accept будет блокироваться до тех пор, пока не будет установлено новое соединение. Таким образом, вы также хотите выбрать () этот сокет. Как только вы примете этот клиент, вы захотите добавить его в свой read_set.

например. Псевдо-код

for (;;) {
    struct timeval tv = { timeout, 0 };
    fd_set read_set;
    FD_ZERO(&read_set);
    FD_SET(listen_sock, &read_set);
    max_fd = max(max_fd, listen_sock);

    /* add all your other other client sockets to thread read_set */
    n = select(max_fd, &read_set, NULL, NULL, tv);
    if (n > 0) {
        if (FD_ISSET(listen_sock, &read_set)) {
            cli = accept(listen_sock);
            /* add to list of clients */
        }
        else  {
            for (int i = 0; i < max_clients; i++) {
                if (FD_ISSET(clients[i], &read_set)) {
                    /* data is waiting. recv */
                    bytes = recv(clients[i], ..)
                    if (bytes <= 0) {
                        /* error or EOF, remove client list, so we don't select on this anymore */
                    }
                }
            }
        }
    }

Обратите внимание, что отправка также может блокироваться, если другой конец не читает активно, а буфер отправки заполнен. Поэтому, если вы отправляете, вы можете проверить, является ли он «отправляемым».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...