2015-08-05 9 views
3

После закрытия клиентского сокета на стороне сервера и выхода из приложения сокет все еще открыт в течение некоторого времени.Сокет открыт после процесса, который открыл его завершение

я могу видеть его с помощью NETSTAT

Every 0.1s: netstat -tuplna | grep 6676  
tcp  0  0 127.0.0.1:6676   127.0.0.1:36065   TIME_WAIT - 

Я использую log4cxx протоколирования и телнет Appender. log4cxx использует apr сокеты. метод Socket :: близко() выглядит следующим образом:

void Socket::close() { 
    if (socket != 0) { 
     apr_status_t status = apr_socket_close(socket); 
     if (status != APR_SUCCESS) { 
      throw SocketException(status); 
     }   
     socket = 0; 
    } 
} 

И это успешно. Но после завершения программы я вижу открытый сокет через netstat, и если он снова запустится, log4cxx не сможет открыть порт 6676, потому что он занят. Я пытаюсь изменить log4cxx. Shutdown гнездо до того близко:

void Socket::close() { 
    if (socket != 0) { 
     apr_status_t shutdown_status = apr_socket_shutdown(socket, APR_SHUTDOWN_READWRITE); 
     printf("Socket::close shutdown_status %d\n", shutdown_status); 
     if (shutdown_status != APR_SUCCESS) { 
      printf("Socket::close WTF %d\n", shutdown_status != APR_SUCCESS); 
      throw SocketException(shutdown_status); 
     } 
     apr_status_t close_status = apr_socket_close(socket); 
     printf("Socket::close close_status %d\n", close_status); 
     if (close_status != APR_SUCCESS) { 
      printf("Socket::close WTF %d\n", close_status != APR_SUCCESS); 
      throw SocketException(close_status); 
     } 
     socket = 0; 
    } 
} 

Но это не помогло, ошибка все еще воспроизводится.

ответ

2

Это не ошибка. Время ожидания (и закрытие) - это дизайн для обеспечения безопасности. Однако вы можете настроить время ожидания. В любом случае, с точки зрения сервера, гнездо закрывается, и вы расслабляетесь с помощью счетчика ulimit, он не оказывает заметного влияния, если вы не выполняете стресс-тест.

2

Как отметил Кальвин, это не ошибка, это особенность. Время ожидания - это состояние сокета, которое говорит, что этот сокет больше не используется, но тем не менее его нельзя использовать повторно.

Представьте, что у вас открыт сокет, а какой-то клиент отправляет данные. Данные могут быть скопированы в сеть или находиться в полете, когда сервер закрывает свой сокет.

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

Взгляните на этот пост для некоторой дополнительной информации: Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?

0

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

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

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

  • Нет связанных вопросов^_^