Подтвердить что ты не робот

С помощью accept() и select() одновременно?

У меня есть программа сетевого сервера, управляемая событиями. Эта программа принимает соединения от других процессов на других хостах. На одном и том же удаленном IP-адресе может быть много коротких соединений из разных портов.

В настоящее время у меня есть цикл while(1), который вызывает accept(), а затем порождает поток для обработки нового соединения. Каждое сообщение закрывается после чтения сообщения. На удаленном конце соединение закрывается после отправки сообщения.

Я хочу устранить накладные расходы на настройку и разрывание соединений путем кэширования открытых FD-фреймов. На стороне отправителя это легко - я просто не закрываю соединения и не поддерживаю их.

На стороне приемника это немного сложнее. Я знаю, что я могу сохранить FD, возвращенный accept() в структуре, и прослушивать сообщения во всех таких сокетах с помощью poll() или select(), но я хочу одновременно одновременно слушать новые соединения через accept() и прослушивать все кэшированные подключения.

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

Есть ли вызов или превосходная методология, которая позволит мне одновременно обрабатывать открытые соединения и отправлять данные по старым соединениям?

4b9b3361

Ответ 1

В прошлый раз, когда я проверил, вы могли бы просто listen в сокете, а затем select или poll, чтобы узнать, произошло ли соединение. Если это так, accept it; он не будет блокировать (но вы можете захотеть действительно должны установить O_NONBLOCK, чтобы быть уверенным)

Ответ 2

вы можете использовать прослушивание, затем использовать select или poll, а затем принять

if (listen (socket_fd, Number_connection) <0 )
{
    perror("listen");
    return 1;
}
fd_set set;
struct timeval timeout;
int rv;
FD_ZERO(&set); /* clear the set */
FD_SET(socket_fd, &set); /* add our file descriptor to the set */

timeout.tv_sec = 20;
timeout.tv_usec = 0;

rv = select(socket_fd + 1, &set, NULL, NULL, &timeout);
if(rv == -1)
{
    perror("select"); /* an error accured */
    return 1;
}
else if(rv == 0)
{
    printf("timeout occurred (20 second) \n"); /* a timeout occured */
    return 1;
}
else
    client_socket_fd = accept (socket_fd,(struct sockaddr *) &client_name, &client_name_len);

Ответ 3

Я бы поставил слушателя в отдельный процесс (поток), чтобы не испортить вещи. И запустите рабочий процесс на другом, чтобы обрабатывать существующие сокеты. На самом деле нет необходимости в неблокирующем слушателе. И нить потоком не работает с двумя потоками.

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

Если вы хотите прослушивать несколько портов и не хотите проводить один процесс на слушателя, я предлагаю вам установить ваш сокет в O_NONBLOCK и сделать что-то вроде:

// loop through listeners here and poll'em for read, when read is successful call accept, get descriptor, pass it to worker and continue listen
    while(1){
        foreach( serverSocket in ServerSockets ){
             if( serverSocket.Poll( 10, SelectRead ) ){
                  clientSocket = serverSocket.Accept();
                  // pass to worker here and release
             }

        }
    }