为什么redis可以绑定到此端口,而我可以';t通过python?

为什么redis可以绑定到此端口,而我可以';t通过python?,python,sockets,redis,Python,Sockets,Redis,我在端口6379上创建了一个服务器套接字,如下所示: >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> s.bind(('localhost', 6379)) >>> s.listen(1) lsof显示它处于侦听状态(为了可读性,我删除了lsof的一些列): 。。。现在我将创建一个客户端套接字并连接 >>> s.connect(('localhos

我在端口6379上创建了一个服务器套接字,如下所示:

>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.bind(('localhost', 6379))
>>> s.listen(1)
lsof显示它处于侦听状态(为了可读性,我删除了lsof的一些列):

。。。现在我将创建一个客户端套接字并连接

>>> s.connect(('localhost', 6379))
。。。lsof节目已建立

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
>s=socket.socket(socket.AF\u INET,socket.SOCK\u STREAM)
>>>s.bind(('localhost',1234))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py”,第228行,meth格式
返回getattr(self.\u sock,name)(*args)
socket.error:[Errno 48]地址已在使用中
有两种可能性:

  • 您会注意到redis绑定到“*”,而python绑定到localhost。因此,当第二次启动redis时,它仍然可以绑定,因为它更一般地在侦听:可能有来自本地主机的传入连接,而redis可以处理该连接,而不是python。但是当redis首先侦听时,现在没有地址可以由其他程序处理,因此不可能在同一端口上打开。有关详细信息,您可以阅读有关UNIX程序
    路由的更多信息

  • 有一个
    SO_REUSEPORT
    选项,允许多个服务器在同一端口上侦听,传入连接被发送到随机服务器。redis可能正在使用它来支持负载平衡。但是,如果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