2015-06-06 3 views
0

Я пишу простой TCP/IP-сервер в Python между двумя клиентами и сервером. В настоящее время, когда я пытаюсь перезапустить программу сразу после ее закрытия на том же порту, оболочка сообщает мне, что порт занят.Должны ли порты быть доступны сразу после закрытия?

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

Мой вопрос в том, что это предположение правильно? Я оставляю открытый сокет или это поведение в норме? Если да, есть ли у кого-нибудь советы относительно того, как я могу найти его?

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

(self.con1, rec1) = self.s.accept() 
    (self.con2, rec2) = self.s.accept() 
    self.con = (self.con1, self.con2) 

бы следующее быть достаточно код, чтобы закрыть эти соединения?

self.con1.close() 
    self.con2.close() 

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

ответ

2

Это нормально. TCP определяет состояние TIME_WAIT для портов, которые сохраняются в течение нескольких минут (в два раза больше срока жизни сегмента), в течение которых они не могут быть повторно использованы. Это показатель целостности данных. Вы можете преодолеть это, установив опцию SO_REUSEADDR перед привязкой сокета.

+0

'SO_REUSEADDR' /' SO_REUSEPORT' позволяет использовать порт, который все еще находится в 'TIME_WAIT'. Чтобы избежать «TIME_WAIT» в первую очередь, вы можете использовать 'SO_LINGER', чтобы отключить затяжку при закрытии, но это не всегда работает. Другим вариантом является использование 'shutdown (SD_RECEIVE)' only, а не 'shutdown (SD_SEND)' или 'shutdown (SD_BOTH)'. Если вы сначала закрываете свой конец соединения И отправляете 'FIN', вы переходите в' TIME_WAIT'. Но вы не должны избегать «TIME_WAIT» в 99.9999999% случаев, он существует по причине защиты сессий от коррупции. –

+0

@RemyLebeau SO_REUSEPORT для UDP, действительно для многоадресной передачи, если я правильно помню. Ничего общего с TIME_WAIT. Способ избежать TIME_WAIT - это конец, который получает первое закрытие, что является еще одним аргументом в пользу объединения пулов. 'shutdown()' на самом деле не имеет большого отношения к этому. Я никогда не пишу о SO_LINGER, так как я не верю, что кто-то никуда не должен возиться с ним. – EJP

+0

'SO_REUSEPORT' также может использоваться для TCP. Он позволяет нескольким потокам/процессам прослушивать один и тот же порт, каждый из которых вызывает 'accept()'. Новый клиент может быть принят любым из них. Полезно для объединения и балансировки нагрузки. Что касается 'TIME_WAIT', вы вводите его только в том случае, если вы первый участник, отправляющий' FIN'. Нет 'FIN' no' TIME_WAIT'. Конечно, пропуская 'FIN' не нравится другой стороне. –

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