套接字错误:地址已在使用中

时间:2015-03-23 18:16:50

标签: python sockets cherrypy

我有一个经常运行的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

同时我的socket被构造为:

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

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

我检查了netstat并且没有看到任何正在侦听端口2112的内容,可能导致问题的原因以及如何进行诊断呢?

谢谢!

3 个答案:

答案 0 :(得分:17)

您可以尝试以下

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

     

这是因为先前的执行使套接字处于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))

答案 1 :(得分:13)

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

ps aux | grep python

,找到进程ID,并通过执行以下操作手动停止:

sudo kill -9 PID

用PID替换PID。

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

答案 2 :(得分:12)

通过以下方式更容易实现:

检查PID(:自从我在127.0.0.1:5000运行以来5000是主机):
.footer { position: absolute; bottom: 0; width: 100%; max-height: 400px; background: #efefef; }
然后将其杀死:
{{ 1}}