为什么socket.accept()会中断未完成的连接?
我搜索了很多帖子,但还是找不到答案。我明白 socket.accept()
实际上是从已经连接的队列中获取一个套接字。而且我知道因为阻塞IO的原因,我们需要依靠并发来处理多个连接。
不过,我想问的是 socket.accept()
还有什么其他作用?它会断开已经建立的连接吗? 在我的实验中,我用一个线程来接受新连接,并且不去处理它。换句话说,我故意不使用 recv()
,因为我想保持每个请求,以便保持多个连接。
我用几个客户端发送消息。令人惊讶的是,只有一个连接能够维持。以下是我的代码。
在服务器端(在Linux服务器上):
import time
import socket
HOST = "0.0.0.0"
PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
while True:
conn, addr = s.accept()
在客户端(在Macbook上):
import socket
HOST = "192.168.0.104"
PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
print('connect')
s.send(b"Hello, world")
当我启动服务器时,第一个客户端被阻塞。当我启动第二个客户端时,第一个客户端出现了错误:
Traceback (most recent call last):
File "/Users/home/xxx/test-client.py", line 14, in <module>
s.send(b"Hello, world")
BrokenPipeError: [Errno 32] Broken pipe
而第二个客户端则被阻塞。
我的问题是:
- 我希望服务器能够保持多个连接,但为什么只有一个能维持?
- 如果
socket.accept()
总是会断开已建立的连接,那为什么并发可以正常工作?
正如 @Mark Tolonen 所说,原因是垃圾回收。当我使用以下代码片段时,我可以看到多个连接得以维持。
#!/usr/bin/env python3
import time
import socket
HOST = "0.0.0.0"
PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
connections = []
while True:
conn, addr = s.accept()
connections.append(conn)
我想感谢大家的帮助,但我想在这里留个言,抱怨一下当前StackOverflow的文化。
在我问这个问题之前,我花了几天时间深入研究套接字,并调查了相关问题。对一些观众来说,这可能看起来很简单,但我真的不明白为什么有人会觉得这是个糟糕的问题。一个人的问题对其他人来说可能总是太简单,但对提问者来说却很难,他只能通过学习来成长。这也给其他可能遇到相同挑战的人提供了机会。让我们保持StackOverflow的开放性。
1 个回答
3
通过 accept()
方法得到的 conn
对象是有引用计数的。当第二个连接被赋值给 conn
时,第一个连接就没有被引用了,这样它就会被垃圾回收机制处理掉,也就是关闭了这个连接。所以你需要把每个连接都保存起来。