Сервер python SimpleHTTPRequestHandler покидает сокет в состоянии TIME_WAIT после выхода - PullRequest
4 голосов
/ 05 марта 2012

У меня написан простой сервер, который расширяет SimpleHTTPRequestHandler

Если я запускаю и останавливаю его без каких-либо запросов к серверу, я могу запустить резервное копирование на тот же порт безпроблема.

При запуске netstat выглядит следующим образом:

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      23392/python

После выполнения запроса netstat выглядит так (даже после завершения запроса):

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      23392/python    
tcp        0      0 127.0.0.1:8001          127.0.0.1:48659         TIME_WAIT   -

Затем я убиваю сервер с помощью Cc, и netstat выглядит следующим образом (на данный момент я не могу перезапустить сервер, потому что порт уже используется):

 sudo netstat -na --program | grep 8001
tcp        0      0 127.0.0.1:8001          127.0.0.1:48674         TIME_WAIT   - 

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

"""
reply is an object that can be json encoded that is written with a response code 200
"""
def send_provider_reply(self, replyobj):
    try:
        str_reply = json.dumps(replyobj)
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        #do we need to send a newline??
        self.wfile.write(str_reply)
    except:
        traceback.print_exc()
        self.send_err(500, 'failed after provider creation')

1 Ответ

5 голосов
/ 06 марта 2012

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

Чтобы дать некоторый контекст: на стороне сервера, с прослушивающими сокетами, есть опция сокета SO_REUSEADDR. Это позволяет прослушивающему сокету успешно связываться до конца TIME_WAIT. Для серверных процессов, которые всегда должны прослушивать один и тот же порт (например, веб-сервер на порту 80, 443), это необходимо.

типичный код Python для сервера может содержать что-то вроде этого:

...
listener = socket(AF_INET, SOCK_STREAM)
listener.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
listener.bind((HOST, PORT))
listener.listen(32)
...
...