【问题标题】:Socket error: Address already in use套接字错误:地址已在使用中
【发布时间】:2015-05-26 20:54:28
【问题描述】:

我有一个经常运行以启动服务器的 CherryPy 脚本。今天我不得不启动和停止它几次以修复配置文件中的一些错误,我猜套接字并没有完全关闭,因为当我再次尝试启动它时,我遇到了这个问题:

[23/Mar/2015:14:08:00] ENGINE Listening for SIGHUP.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGTERM.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGUSR1.
[23/Mar/2015:14:08:00] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.

[23/Mar/2015:14:08:00] ENGINE Started monitor thread 'Autoreloader'.
[23/Mar/2015:14:08:00] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Mar/2015:14:08:00] ENGINE Error in HTTP server: shutting down
Traceback (most recent call last):
  File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/process/servers.py", line 188, in _start_http_thread
    self.httpserver.start()
  File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1848, in start
    raise socket.error(msg)
error: No socket could be created

我编辑了 CherryPy 的 wsgiserver2.py 以查看 socket.error 的详细信息,error.strerror

98  (98, 'Address already in use') Address already in use

同时我的套接字构造为:

af = 2
socktype = 1
proto = 6
canonname = ''
sa = ('0.0.0.0', 2112)
self.bind(af, socktype, proto)

(这不是确切的代码,但这就是触发错误时的值)

我检查了 netstat,但在 2112 端口上没有看到任何监听,可能是什么导致了问题,我该如何诊断它?

谢谢!

【问题讨论】:

    标签: python sockets cherrypy


    【解决方案1】:

    你可以试试下面的

    from socket import *
    
    sock=socket()
    sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    # then bind
    

    来自文档:

    SO_REUSEADDR 标志告诉内核重用处于 TIME_WAIT 状态的本地套接字,而无需等待其自然超时到期。

    这里是完整的解释:

    多次运行示例,执行之间的延迟太小,可能会导致此错误:

    socket.error: [Errno 98] Address already in use

    这是因为之前的执行让socket处于TIME_WAIT状态,不能立即重用。

    有一个套接字标志要设置,为了防止这种情况,socket.SO_REUSEADDR:

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    

    【讨论】:

    • 谢谢,但我在运行的代码中看到 CherryPy 确实做到了这一点。第 1884 行:self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 我在该行后面放了一个打印语句,看看它是否没有被执行,但似乎是。
    • 问题似乎出在 self.socket.bind(bind_addr) 和 bind_addr ('0.0.0.0', 2112)
    • @AndrewLatham,self.socket 是用于绑定的套接字吗?
    • 是的。我还尝试了 netstat -n -A inet,在 2112 上看到了很多 TIME_WAIT、CLOSE_WAIT 和 ESTABLISHED 的东西。
    • @AndrewLatham,那么这不是 Python 的问题。您可以使用ps ax | grep 2112 尝试查找使用此端口的程序。之后,你可以尝试杀死所有python的进程:killall python
    【解决方案2】:

    您可以通过以下方式找到该进程并kill它:

    ps aux | grep python
    

    ,找到进程 ID,然后手动停止它:

    sudo kill -9 PID
    

    用您的 PID 替换 PID。

    在使用 Flask/CherryPy 进行测试时,我经常需要这样做。有兴趣看看是否有更简单的方法(例如首先防止它)

    【讨论】:

    • killall python 甚至sudo killall python 会不会更方便?
    • -9 是什么意思?
    • @kurumkan 而不是说“请关闭”它只是......停止运行该进程的代码。这总是会导致数据丢失;这只是您是否需要这些数据的问题。
    【解决方案3】:

    通过以下方式更容易做到:

    检查 PID(:5000 是主机,因为我一直在 127.0.0.1:5000 上运行):
    $ lsof -i :5000
    然后杀了它:
    $ sudo kill -9 PID

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 2013-07-01
      • 2018-01-30
      • 2021-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多