python - 套接字侦听()接受一个太多的连接
问题描述
我试图将 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 个连接并且不在队列中保留任何连接?
解决方案
无论文档如何:
socket.listen([backlog])
使服务器接受连接。如果指定 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()
在接受另一个之前连续调用并关闭它。如果客户端连接、发送查询并且在设定的时间内没有得到响应,则客户端可以使用超时。
推荐阅读
- r - 交互作用中的生存分析参考
- javascript - facebook 图像 url 到 blob 数据
- ruby-on-rails - 如何测试是否在使用 RSpec 从 Rails 中的数据库中提取的特定对象上调用方法?
- javascript - 除了 App.js 之外没有代码的全新项目:错误:无效的钩子调用。Hooks 只能在函数组件的主体内部调用
- python - 跳过连接第一个值
- algorithm - 如何简化时间复杂度方程?
- jestjs - Jest + Nock:如果发出非模拟请求,如何使测试失败?
- angular - Angular:具有外部服务的组件抽象类
- python - googleapis / python-bigquery:Client.load_dataframe_to_table 失败并出现 PyArrow “TypeError:需要一个整数(获取类型 str)”
- python - Python 请求(网页抓取)