Python 3.x 使用套接字和;多线程
我正在创建两个简单的服务器-客户机python脚本,它们响应命令。也就是说,服务器打开一个套接字,然后客户端连接,发送一条简单的消息,然后服务器将消息回显给客户端,然后客户端打印消息。我正在尝试使这个多线程,这就是问题所在 我正在学习真正的Python教程,并且能够成功地运行和。我理解基本概念,能很好地理解代码。因此,我向服务器程序添加了代码,使其成为多线程: server-multi-threaded.py 这是客户端程序 client.py 运行多线程服务器时,我收到以下回溯:Python 3.x 使用套接字和;多线程,python-3.x,multithreading,sockets,networking,Python 3.x,Multithreading,Sockets,Networking,我正在创建两个简单的服务器-客户机python脚本,它们响应命令。也就是说,服务器打开一个套接字,然后客户端连接,发送一条简单的消息,然后服务器将消息回显给客户端,然后客户端打印消息。我正在尝试使这个多线程,这就是问题所在 我正在学习真正的Python教程,并且能够成功地运行和。我理解基本概念,能很好地理解代码。因此,我向服务器程序添加了代码,使其成为多线程: server-multi-threaded.py 这是客户端程序 client.py 运行多线程服务器时,我收到以下回溯: Connec
Connection from 127.0.0.1
Server received 13 bytes from 127.0.0.1
Exception in thread Thread-1:
Traceback (most recent call last):
File "D:\Program Files\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
self.run()
File "D:\Program Files\Python\Python37\lib\threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "server-multithreaded-new.py", line 17, in handler
conn.sendall(data)
OSError: [WinError 10038] An operation was attempted on something that is not a socket
此外,客户端没有收到完整的“Hello,World!”消息(如非多线程版本)。相反,它只获取一个空字节字符串:
Received b''
我的猜测是,当数据仍在传输时,套接字似乎正在关闭,但我不知道为什么。毕竟,我的理解是,带有上下文管理器的应该智能地、自动地处理关闭操作
有人知道为什么会发生这种情况,以及我如何解决它吗
毕竟,我的理解是,具有上下文管理器的
巧妙地自动处理关闭
好的,是和否。当执行以
前缀离开范围时,上下文管理器将关闭套接字,也就是说,几乎在线程启动后立即关闭。同时,您的线程仍在运行(与主线程并行),并且在启动后的几毫秒内(或者甚至可能在启动之前,取决于操作系统如何调度新线程),它会发现主线程已从其下方关闭其套接字
特别是,主线程中的上下文管理器不够智能,无法意识到您已经将对套接字的引用传递给了一个正在使用它的单独线程;它总是在退出with作用域时关闭套接字,句号为
解决这个问题的简单方法是让您的网络线程负责关闭套接字,而不是主线程;例如,您可以将上下文管理器代码/with块放置在网络线程中,而不是主线程中,如下所示:
# network I/O thread
def handler(conn, addr):
with conn:
while True:
data = conn.recv(BUFFER_SIZE)
print(f"Server received {len(data)} bytes from {addr[0]}")
if not data:
break
conn.sendall(data)
# main thread
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print(f"Connection from {addr[0]}")
Thread(target=handler, args=(conn, addr)).start()
Received b''
# network I/O thread
def handler(conn, addr):
with conn:
while True:
data = conn.recv(BUFFER_SIZE)
print(f"Server received {len(data)} bytes from {addr[0]}")
if not data:
break
conn.sendall(data)
# main thread
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print(f"Connection from {addr[0]}")
Thread(target=handler, args=(conn, addr)).start()