【问题标题】:socket listen() accepting one too many connections [duplicate]套接字侦听()接受一个太多的连接[重复]
【发布时间】:2021-09-13 22:17:30
【问题描述】:

我试图将 Python 服务器限制为仅接受来自一个客户端的连接,但我注意到 Python 服务器总是接受一个太多的连接。这是服务器代码:

import socket 
import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(0)
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
while True:
    time.sleep(1000)
    clientsocket.send(bytes("Welcome to server 1!", "utf-8"))

我希望这一次只允许一个客户端连接,因为队列中不允许有任何客户端连接 (s.listen(0))。但是,我发现此代码允许我在出现错误之前连接两个客户端。这是我的客户正在连接:

>>> import socket
>>> socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((socket.gethostname(), 1234))
>>> socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((socket.gethostname(), 1234))
>>> socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((socket.gethostname(), 1234))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it

第一个客户端被接受,这是预期的。第二个客户端成功连接,这是我没想到的,因为服务器已经有一个连接并且队列中允许 0 个连接。在第三个客户端尝试连接并被拒绝之前,我们不会失败。

如果我们将 listen() 参数设置为 1,我们将被允许 3 个连接(1 个当前连接,2 个在队列中)。如果我们将其增加到 2,则允许有 4 个连接(1 个当前连接,3 个在队列中)。这种模式仍在继续。

我如何指定我的服务器应该允许 1 个连接而不在队列中保留任何连接?

【问题讨论】:

  • 无法复制。使用您的代码,当客户端连接时,我在服务器端收到 broken pipe 错误。
  • 嘿抱歉我刚刚更新了服务器端代码。应该管用。我只是想简化代码,但意识到我设置它的方式,它会立即尝试将数据发送回一个不再存在的套接字,因为我们没有存储它。

标签: python sockets


【解决方案1】:

不管documentation:

socket.<b>listen</b>([<em>backlog</em>])
使服务器接受连接。如果指定 backlog,则必须至少为 0(如果较低,则设置为 0);它指定在拒绝新连接之前系统将允许的未接受连接的数量。如果未指定,则选择默认的合理值。

测试表明不接受连接的最小值是1,而不是backlog + 1。这可能取决于操作系统。我使用的是 Windows 10。请注意,我不接受以下任何连接,只是连接直到它们被拒绝。

In [1]: from socket import *
   ...: for backlog in range(-1,6):
   ...:     s=socket()
   ...:     s.bind(('',5000))
   ...:     s.listen(backlog)
   ...:     c=[]
   ...:     try:
   ...:         while True:
   ...:             a=socket()
   ...:             a.connect(('localhost',5000))
   ...:             c.append(a)
   ...:     except ConnectionRefusedError:
   ...:         print(f'{backlog=} successful_connections={len(c)}')
   ...:
backlog=-1 successful_connections=1
backlog=0 successful_connections=1
backlog=1 successful_connections=1
backlog=2 successful_connections=2
backlog=3 successful_connections=3
backlog=4 successful_connections=4
backlog=5 successful_connections=5

这是有道理的。您需要至少有一个未接受的连接排队,否则.accept() 将一无所有。

如果您只想要一个接受连接,请连续调用.accept() 并在接受另一个之前关闭它。如果客户端连接、发送查询并且在设定的时间内没有得到响应,则客户端可以使用超时。

【讨论】:

    猜你喜欢
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2021-12-16
    • 2017-04-27
    • 1970-01-01
    • 2016-07-08
    • 2012-08-08
    相关资源
    最近更新 更多