2

我有一个在 CentOS 6.4/64 位下运行的 Python 协议。我在哪里有 TCP 服务器端口 7007。在某些情况下,例如更新新版本或维护或即时重启以刷新缓冲区,我需要重新启动应用程序:

服务器.py:

class AServer(threading.Thread):
  def __init__(self, port):
    threading.Thread.__init__(self)
    self.port = port

  def run(self):
    host = ''
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, self.port))
    print bgcolors.BOOT
    s.listen(1)
    conn, addr = s.accept()
    print bgcolors.OK + 'contact', addr, 'on', self.now()

    while 1:
      try:
        data = conn.recv(1024)
      except socket.error:
        print bgcolors.OK + 'lost', addr, 'waiting..'
        s.listen(1)
        conn, addr = s.accept()
        print bgcolors.OK + 'contact', addr, 'on', self.now()
        continue
      if not data:
        ..... 
      ...

t = AServer(7007)
t.start()

即时重新启动紧急(期望在 1 秒内运行)但失败:

$ ps aux | awk '/server.py/ {print $2}' | head -1 | xargs kill -9;
$ nohup python /var/tmp/py-protocol/server.py &
[root@IPSecVPN protocol]# python server.py
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "server.py", line 236, in run
    s.bind((host, self.port))
  File "<string>", line 1, in bind
error: [Errno 98] Address already in use
4

3 回答 3

6

您的套接字处于 TIME_WAIT 状态,这就是为什么即使您的程序已退出该地址仍在使用中的原因。您可以在套接字上设置 SO_REUSEADDR 以在套接字退出 TIME_WAIT 状态之前重用它。Python 文档建议如下:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
于 2013-09-07T19:18:01.527 回答
0

好吧,TCP 有一个 TIMEWAIT 计时器,可以保持连接一段时间(在大多数操作系统上大约为 2 分钟)。因此,如果您已经绑定并连接了一个端口,那么关闭它可能会将其置于 TIMEWAIT 状态。更准确地说,只有一侧的 TCP 连接处于 TIMEWAIT 状态。

这是关于 TIMEWAIT 的一个很好的讨论:服务器端的许多 TIME_WAIT 的成本是多少?

同意@clj 解决方案,设置 SO_REUSEADDR 是个好主意(+1)。

于 2013-09-07T19:10:20.707 回答
0

打开你的终端:

ps aux || grep

列出所有正在运行的服务并找到您要杀死的 id。

sudo kill -9 <id you want to kill>
于 2022-02-10T07:52:56.540 回答