2016-09-07 7 views
0

Я пытаюсь установить параметры сокета для клиентского сокета, возвращенного из функции accept(). Но они не устанавливаются правильно.Настройка sockopt для клиентского сокета, возвращаемого из accept()

Моя цель - тайм-аут клиента после определенного времени бездействия. Но сервер все равно должен принимать другие клиентские соединения.

Ниже приведен мой код, где я устанавливаю параметр сокета. Не могли бы вы предложить, что не так?

while ((new_sock_fd = accept(socket_fd, (struct sockaddr *) &cli_addr, &clilen)) > 0) 
{ 
    if (new_sock_fd < 0) 
     printf("Accept Error"); 
    else 
    { 
     struct timeval timeout;  
     timeout.tv_sec = 10; 
     timeout.tv_usec = 0; 
     if (setsockopt(new_sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) 
      error("setsockopt failed\n"); 
     if (setsockopt(new_sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) 
      error("setsockopt failed\n"); 
     pthread_create(&thread, NULL, client_handler, (void *) (intptr_t)new_sock_fd); //intptr_t is big enough to hold the integer prt 
    } 
} 
+1

Как узнать, что параметры не установлены? Ошибка 'setsockopt()' с ошибкой? Возвращает ли 'getsocktop()' значения, которых вы не ожидаете? Разве сокет просто ведет себя иначе, чем ожидалось? Если да, то как? На какой платформе работает этот код? На большинстве платформ SO_RCVTIMEO и SO_SENDTIMEO действительно используют структуру 'timeval' в качестве входных данных. Но в Windows они вместо этого берут 'DWORD'. –

+1

Кроме того, ваше сообщение «Принять ошибку» никогда не будет сообщено, так как ваш цикл входит только в тело цикла, когда 'new_socket_fd> 0'. Если вы хотите выполнить обработку ошибок на 'accept()', вы должны переместить ее внутри цикла. –

ответ

1

Моя цель состоит в том, чтобы время ожидания клиента после определенного времени бездействия . [...] можете ли вы предложить, что когда не так ..?

Я подозреваю, что не так, что вы не понимаете, что должны делать SO_RCVTIMEO и SO_SNDTIMEO. Из man page:

SO_RCVTIMEO и SO_SNDTIMEO Указать на получение или отправка TimeOuts до сообщения об ошибке. Аргумент - это struct timeval. Если на этот период времени блокируются входные или выходные функции , и данные отправляются или принимаются , то возвращаемым значением этой функции будет сумма данных ; если данные не были переданы, а тайм-аут был достигнут, тогда -1 возвращается с переменной errno, установленной в EAGAIN или EWOULDBLOCK, или EINPROGRESS (для подключения (2)) так же, как если бы сокет был указан как неблокирующий. Если таймаут установлен на ноль ( по умолчанию), то операция никогда не будет таймаутом.

... но похоже, что вы хотите, чтобы TCP-соединение автоматически закрывалось через определенное количество времени без трафика по TCP-соединению, что не то же самое, что и принудительный вызов() или recv(), чтобы вернуться через определенное время.

Если вы ищете механизм для закрытия простоя TCP-соединения, вы можете реализовать это самостоятельно, записав текущее время всякий раз, когда данные отправляются или принимаются в сокете. В более позднее время (например, после отправки() или recv() раза) вы можете вычесть записанный последний трафик, наблюдаемый вовремя, с текущего времени; если разница больше вашего значения времени ожидания, вызовите функцию close() в гнездо самостоятельно.

+0

Или просто используйте 'select()' или 'epoll()' для реализации тайм-аута вместо этого. Поместите сокет в неблокирующий режим, а затем 1) перед чтением, опросом для чтения с таймаутом; 2) если отправка не выполняется с помощью «EAGAIN» или «EWOULDBLOCK», опрос на возможность записи с таймаутом. Если время работы отключено, закройте соединение. –