在多线程程序中添加time.sleep可以解决python中的UnicodeDecodeError问题



以下是我在程序中创建的线程的基本概念:

Main thread
|
ListenerCreator(The WebSocketServer thread)  ---> Several listener threads(using log())

因此,主线程创建了一个ListenerCreator线程,该线程连接到多个客户端,并为每个客户端创建一个侦听器线程。以下简要介绍了侦听线程的作用:第1版:我正在使用WebSockets从我的客户端读取/写入数据。为此,我制作了自己的服务器。有一个框架协议是标准规定的——我正在使用它。在客户端,我只是简单地使用WebSocket.send()和"揭开面纱";根据协议中给出的指令发送消息(参见上面链接中的第5.3节)。如果有人要求,我愿意提供服务器代码,不过,这里有一个简短的概述:

class WebSocketServer:
def start(): 
#Open server socket, bind to host:port
while True:
#Accept client socket, start a new listener thread for self.log(client)
def log(client):
#Receive data using socket.socket.recv(1024)
#Unmask data as per the protocol
#Decode using data.decode("utf-8")
#Append to data_q while holding data_q_lock

还有其他方法,比如方便发送、关闭、握手等等

同时在主线程中:

while breaking!=len(client_list):
#time.sleep(0.5)    
with data_q_lock:
for i in range(len(data_q)):
mes = data_q.pop()
for m in client_list:
if "#DONE"== mes:
breaking += 1
if(mes[:len("#COUNT:")] == "#COUNT:"):
print(mes)

所以这个循环基本上是这样做的:循环通过data_q,如果消息以"开头#COUNT";,打印该消息#DONE";消息,退出循环。如果time.sleep未被注释,则此代码可以工作,但是如果没有time.sleeplog函数,我会得到一个UnicodeDecodeError。此外,我只得到错误有时,有时程序工作得很好。(顺便说一句,客户端每次都发送相同的数据)所以,我的问题是,为什么需要睡眠时间?我认为这与python中的GIL有关,因为time.sleep发布了GIL。然而,即使在阅读了它之后,我也无法解决的问题

当前没有关于侦听器如何从套接字读取数据的信息。然而,这似乎是由通常对套接字的误解引起的。

通过套接字发送的数据不会以任何方式被套接字"框化"。想象一下,如果我在一个插座里发送了三次"你好"的信息。然后,就像在没有换行的情况下写入文件一样,以下内容将在套接字上流动:

hellohellohello

现在想想读者。。。在读取数据时,它如何知道一条消息("hello")从哪里开始,以及下一条消息从哪里开始?除非发送方和接收方就如何"构建"数据达成一致,否则它不能。这可以通过达成一些协议来实现,比如:

  • null终止数据;或
  • 固定大小的消息;或
  • 以大小为前缀的消息

当然,它会变得更加复杂,即使您已经决定了如何构建数据,也不能保证socket.recv会返回"完整"消息。。。它将简单地返回当时缓冲区中发生的任何数据。它可能是半条信息,也可能是一条半条信息。您的工作是整理从套接字读取的数据并将其划分为消息。

转到您的问题,您正在发送utf-8数据的位置。读卡器如何知道已读取完整的utf-8数据消息?很可能,这里发生的情况是,您只收到部分消息。。。还有更多的东西要到。

特别是,一个有效的utf-8字符可以由一个以上的字节组成。因此,如果您的部分消息在字符的多字节utf-8表示的中间结束,那么您肯定无法对其进行解码

最新更新