* nix и C ++ пишут неблокирующий сокет сервер - PullRequest
0 голосов
/ 17 января 2012

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

Является ли следующее правильное предположение? С неблокирующим сервером я обычно должен открыть сокет, затем установить его флаги в неблокирующее состояние, связать его и начать вызывать select для чтения файлового дескриптора и ждать его заполнения? Мне нужно удалить старую блокировку вызова «accept ()», которая ждала бесконечно .. Если я попытаюсь позвонить, примите, это будет -1 для меня сейчас ...

Вот соответствующий код, который я сейчас пытаюсь

fd_set incoming_sockets;
....
int listener_socket, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
....
listener_socket = socket(AF_INET, SOCK_STREAM, 0); //get socket handle
int flags = fcntl(listener_socket, F_GETFL, 0);
if( fcntl(listener_socket, F_SETFL, flags | O_NONBLOCK) < 0 )
    log_writer->write_to_error_log("Error setting listening socket to non blocking", false);
memset(&serv_addr, 0, sizeof(struct sockaddr_in));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
....
if (bind(listener_socket, (struct sockaddr *) &serv_addr,
        sizeof(struct sockaddr_in)) < 0)
{
    log_writer->write_to_error_log("Unable to bind socket, aborting!", true);
}
....
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

int ready_sockets = 0;

listen(listener_socket,1);

FD_ZERO(&incoming_sockets); 
FD_SET(listener_socket, &incoming_sockets); 

while(true)
{

ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout  );

if(ready_sockets == 0)
    {
        //I loop here now for ever
        std::cout << "no new sockets available, snooze 2\n";
        sleep(2);
    } else
    {
    std::cout << "connection received!\n";

Ответы [ 2 ]

1 голос
/ 17 января 2012

Поскольку вы не показываете весь цикл, я не знаю, сделаете ли вы это позже, но вы должны инициализировать наборы дескрипторов и структуру тайм-аута перед каждым вызовом select.

0 голосов
/ 17 января 2012

Вы должны переместить макросы fd_zero () fd_set () внутри цикла, select на самом деле изменит битовые маски в fd_sets (и значение тайм-аута). Реинициализируйте их на каждой итерации. Также проверьте для выбора, возвращающего -1 и связанного с ним errno (EPIPE ...)

while(true)
{

FD_ZERO(&incoming_sockets); 
FD_SET(listener_socket, &incoming_sockets); 



ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout  );

if(ready_sockets == 0)
    {
      ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...