gpt4 book ai didi

python - 在此 Python 3 客户端-服务器示例中,客户端不能发送多条消息

转载 作者:太空宇宙 更新时间:2023-11-03 15:11:43 24 4
gpt4 key购买 nike

这是一个简单的客户端-服务器示例,其中服务器返回客户端发送的任何内容,但相反。

服务器:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024)
print('RECEIVED: ' + str(self.data))
self.request.sendall(str(self.data)[::-1].encode('utf-8'))

server = socketserver.TCPServer(('localhost', 9999), MyTCPHandler)
server.serve_forever()

客户:

import socket
import threading

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('localhost',9999))

def readData():
while True:
data = s.recv(1024)
if data:
print('Received: ' + data.decode('utf-8'))

t1 = threading.Thread(target=readData)
t1.start()

def sendData():
while True:
intxt = input()
s.send(intxt.encode('utf-8'))

t2 = threading.Thread(target=sendData)
t2.start()

我从在 Google 上找到的示例中获取了服务器,但客户端是从头开始编写的。这个想法是让客户端可以无限期地从服务器发送和接收数据。

与客户端一起发送第一条消息。但是,当我尝试发送第二条消息时,出现此错误:

ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

我做错了什么?

最佳答案

对于 TCPServerhandle处理程序的方法被调用一次以处理整个 session 。这在文档中可能并不完全清楚,但是 socketserver 就像 stdlib 中的许多库一样,旨在作为清晰的示例代码以及直接使用,这就是文档链接到的原因the source ,您可以清楚地看到每个连接只会调用一次 handle(TCPServer.get_request 定义为仅在套接字上调用 accept)。

因此,您的服务器接收一个缓冲区,发回一个响应,然后退出,关闭连接。

要解决这个问题,您需要使用循环:

def handle(self):
while True:
self.data = self.request.recv(1024)
if not self.data:
print('DISCONNECTED')
break
print('RECEIVED: ' + str(self.data))
self.request.sendall(str(self.data)[::-1].encode('utf-8'))

一些旁注:

首先,单独使用 BaseRequestHandler 一次只能处理一个客户端连接。作为introduction in the docs说:

These four classes process requests synchronously; each request must be completed before the next request can be started. This isn’t suitable if each request takes a long time to complete, because it requires a lot of computation, or because it returns a lot of data which the client is slow to process. The solution is to create a separate process or thread to handle each request; the ForkingMixIn and ThreadingMixIn mix-in classes can be used to support asynchronous behaviour.

这些混合类在介绍的其余部分中有进一步描述,并且 farther down the page , 和 at the bottom ,最后有一个很好的例子。文档没有说清楚,但是如果您需要在处理程序中执行任何 CPU 密集型工作,您需要 ForkingMixIn;如果您需要在处理程序之间共享数据,您需要 ThreadingMixIn;否则你选择哪个并不重要。

请注意,如果您正在尝试处理大量并发客户端(超过几十个),那么 fork 和线程都不合适——这意味着 TCPServer 并不合适。对于这种情况,您可能需要 asyncio ,或第三方库(Twisted、gevent 等)。


调用 str(self.data) 是个坏主意。您将获得字节串的源代码兼容表示,例如 b'spam\n'。您想要的是将字节字符串解码为等效的 Unicode 字符串:self.data.decode('utf8')


无法保证一侧的每个 sendall 都与另一侧的单个 recv 匹配。 TCP 是字节流,而不是消息流;完全有可能在一次 recv 中收到半条消息,而在下一次收到两条半消息。当系统在轻负载下使用本地主机上的单个连接进行测试时,它可能看起来“有效”,但是一旦您尝试部署任何假设每个 recv 只收到一条消息的代码,您的代码将中断。参见 Sockets are byte streams, not message streams更多细节。请注意,如果您的消息只是文本行(如示例中所示),请使用 StreamRequestHandler 及其 rfile 属性,而不是 BaseRequestHandler及其 request 属性,简单地解决了这个问题。


您可能想要设置 server.allow_reuse_address = True。否则,如果您退出服务器并过快地重新启动它,它将失败并出现类似 OSError: [Errno 48] Address already in use 的错误。

关于python - 在此 Python 3 客户端-服务器示例中,客户端不能发送多条消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25730769/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com