сервер сокетов в потоке, не освобождающий порт после завершения процесса - PullRequest
0 голосов
/ 14 марта 2012

Следующий код запускает сервер сокетов в потоке.Сокет клиента отправляет «client: hello» на сервер, а сокет сервера получает и отвечает «server: world».

import socket
import threading

def server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 12345))
    sock.listen(1)
    req, addr = sock.accept()
    print req.recv(1024)
    req.sendall('server: world')

def client():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('127.0.0.1', 12345))
    sock.sendall('client: hello')
    print sock.recv(1024)

def main():
    t = threading.Thread(target=server)
    t.start()
    client()

if __name__ == '__main__':
    main()

Он работает нормально, как и ожидалось в первый раз, но во второй раз,если вы не будете ждать несколько секунд, пока сервер освободит сокет, и если вы попробуете это на компьютере с Linux или Mac (Windows не получает его каким-либо образом), вы столкнетесь с этой ошибкой:

Traceback (most recent call last):
  File "socket_send_receive.py", line 24, in <module>
    main()
  File "socket_send_receive.py", line 21, in main
    client()
  File "socket_send_receive.py", line 14, in client
    sock.connect(('127.0.0.1', 12345))
  File "<string>", line 1, in connect
socket.error: [Errno 111] Connection refused
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/home/cxuan/python/2.6/lib/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/home/cxuan/python/2.6/lib/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "socket_send_receive.py", line 6, in server
    sock.bind(('127.0.0.1', 12345))
  File "<string>", line 1, in bind
error: [Errno 98] Address already in use

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

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

socket.SO_REUSEADDR

1 Ответ

3 голосов
/ 14 марта 2012

Когда сокет закрыт, он заканчивается в состоянии, называемом STATE_WAIT (см. эту диаграмму ).Пока сокет находится в этом состоянии, никто другой не может использовать этот адрес (пара ip-номер / порт), если в сокете не установлена ​​опция SO_REUSEADDR.

См., Например, статью Википедии на TCP для получения дополнительной информации о том, как работает TCP и различных состояний .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...