我在端口6379上创建了一个服务器套接字,如下所示:
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.bind(('localhost', 6379))
>>> s.listen(1)
lsof显示它处于LISTEN状态(为了便于阅读,我删除了一些lsof的列):
Python 13800 IPv4 TCP localhost:6379 (LISTEN)
...现在我将创建一个客户端套接字并连接...
>>> s.connect(('localhost', 6379))
... lsof显示ESTABLISHED ...
Python 13800 IPv4 TCP localhost:6379 (LISTEN)
Python 13838 IPv4 TCP localhost:63075->localhost:6379 (ESTABLISHED)
然后我启动我的redis服务器。这是所有似乎都在使用6379的东西,由lsof提供:
Python 13800 IPv4 TCP localhost:6379 (LISTEN)
Python 13838 IPv4 TCP localhost:63075->localhost:6379 (ESTABLISHED)
redis-ser 13855 IPv6 TCP *:6379 (LISTEN)
redis-ser 13855 IPv4 TCP *:6379 (LISTEN)
我会在redis上添加一些东西来启动另一个连接:
>>> r = redis.StrictRedis('localhost', 6379)
>>> r.set('foo', 'bar')
......我可以在lsof中看到......
Python 13800 IPv4 TCP localhost:6379 (LISTEN)
Python 13838 IPv4 TCP localhost:63075->localhost:6379 (ESTABLISHED)
redis-ser 13855 IPv6 TCP *:6379 (LISTEN)
redis-ser 13855 IPv4 TCP *:6379 (LISTEN)
redis-ser 13855 IPv6 TCP localhost:6379->localhost:63084 (ESTABLISHED)
所以我的问题是......如果我按相反的顺序这样做,例如首先运行“redis-server”,然后尝试将套接字绑定到端口6379,我得到一个“已经在使用的地址”错误。
为什么在Python已经允许的情况下允许redis使用该端口,但反之则不然?
例如......
redis --port 1234
...工作正常,但是如果我在运行时尝试创建一个Python套接字:
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.bind(('localhost', 1234))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 48] Address already in use
答案 0 :(得分:1)
两种可能性:
你会注意到redis被绑定到&#34; *&#34;而python绑定到localhost。因此当第二次启动redis时,它仍然允许绑定,因为它更普遍地监听:可能有一个传入连接不是来自localhost,而redis可以处理而不是python。但是当redis首先监听时,现在没有可以由不同程序处理的地址,因此无法在同一端口上打开。您可以阅读有关UNIX程序route
的更多信息以获取详细信息。
有一个SO_REUSEPORT
选项,允许多个服务器在同一端口上侦听,并将传入连接发送到随机服务器。 Can two applications listen to the same port? redis可能正在使用它来支持负载平衡。如果python程序没有指定这个标志,我希望它的监听被拒绝。