2011-02-24 5 views
1

Я разрабатываю многопоточный сервер с пулом потоков. Эта система предназначена для использования постоянных TCP-соединений, поскольку клиенты будут поддерживать соединения вблизи 24/7. Проблема, с которой я сталкиваюсь, заключается в том, как управлять отключением. В настоящее время соединение происходит через «accept (listen_fd ....)» и присваивается структуре рабочего порядка. Эта структура сбрасывается в рабочую очередь и подбирается потоком. С этого момента этот поток посвящен текущему соединению. Мой код внутри нити:Выключение Постоянного TCP-соединения. (C многопоточный сервер)

/* Function which runs in a thread to handle a request */ 
void * 
handle_req(void *in) 
{ 
    ssize_t n; 
    char read; 
    /* Convert the input to a workorder_ptr */ 
    workorder_t *workorder_ptr = (workorder_t *)in; 

    while(!serv_shutdown 
     && (n=recv(workorder_ptr->sock_fd,&read,1,0) != 0)) 
    { 
    printf("Read a character: %c\n",read); 
    } 
    printf("Peer has shutdown.\n"); 

    /* Free the workorder memory */ 
    close(workorder_ptr->sock_fd); 
    free(workorder_ptr); 
    return NULL; 
} 

который просто слушает сокет и вторит символы бесконечно, и работает правильно, когда клиент разрывает соединение. Вы видите часть «! Serv_shutdown» в цикле while - это моя попытка заставить поток вырваться из своего цикла по сигналу выключения. Когда SIGINT пойман, глобальная переменная установлена ​​в 1. К сожалению, программа в настоящее время блокирует оператор recv и не проверяет этот флаг до тех пор, пока не будет прочитан другой символ. Я хочу избежать этого, поскольку это может быть произвольное количество времени, прежде чем другой персонаж будет отправлен по этому соединению.

Кроме того, я прочитал в другом сообщении, что лучше использовать «выбрать», чем «принять», чтобы ждать сокета, но я не совсем понял. Будете ли вы делать выбор, чтобы подождать, а затем принять сразу после этого? Я не уверен, как select создает соединение сокета. Я спрашиваю об этом, потому что, если мое понимание выбора будет выяснено, возможно, оно относится к вопросу, который я задаю?

Также, как определить случай, когда соединение просто отключается?

Спасибо!

EDIT Я думаю, что, возможно, наконец, нашел решение, после дальнейшего копания:

Wake up thread blocked on accept() call

В принципе, я мог бы создать глобальную трубу и иметь каждый поток сделать выбор по своему socket_fd а также эта глобальная труба. Затем, когда сигнал пойман, я просто напишу что-нибудь в трубку. Все потоки должны быть разбужены, нет?

ответ

1

Ну, на FreeBSD, MacOSX и, возможно, в другом месте есть вызов kevent(), который позволяет прослушивать широкий диапазон системных событий, включая запросы на соединение и сигнализацию, когда данные поступают в сокет. Он решит все ваши проблемы аккуратным способом, но он не переносится. Существуют такие libsent libevent и libev, которые обертывают функциональные возможности OS, такие как kevent() для BSD, epoll() для Linux и так далее. Может быть, это поможет вам.

Смежные вопросы