从服务器发送消息时出现 SocketIO"数据包队列为空,正在中止"错误



我在从WSGI服务器向SocketIO客户端发送SocketIO消息时遇到了问题。另一种方式(客户机到服务器)的消息工作正常,没有任何问题。代码是用Python编写的,使用python-socketio包和eventlet来创建WSGI服务器。服务器和客户机在同一台Windows机器上的不同控制台中运行。通过点击按钮发送消息。

结果如下:

  1. 在一个控制台中,启动服务器并显示一个带有按钮的窗口(发送消息)出现。
  2. 在另一个控制台中,启动客户机。两扇窗按钮出现-一个按钮启动到服务器的连接,另一个按钮发送消息。
  3. 点击客户端的"Connect"按钮,连接完成没有问题。
  4. 点击客户端的"发送Msg"按钮,发送的数据为在服务器的控制台中打印(这完全可以正常工作)
  5. 服务器的"发送消息"按钮被点击。在客户端控制台中,有一段时间什么都没有发生(我假定是当服务器再次轮询时)然后执行客户端的disconnect()函数(这不是

根据服务器的客户端是否发送第一条消息,客户端控制台显示的消息略有不同。

  • 如果服务器发送第一个消息,那么当客户端发送时这只是disconnect()函数的print语句的消息显示。
  • 如果客户端发送了第一个消息,那么当服务器发送它的消息时,"数据包队列"如果为空,则显示aborting ",后跟?中的print语句断开()函数。

为什么客户端没有接收到服务器发出的消息?

下面是显示该问题的完整服务器和客户端代码:

服务器代码:

from PyQt5.QtWidgets import QPushButton, QDialog, QApplication
import socketio, sys, eventlet
from threading import Thread
class My_Class(QDialog):
def __init__(self, parent=None):
super(My_Class, self).__init__(parent)

self.setWindowTitle("My SocketIO Server")
self.resize(300,150)
self.move(300, 200)

self.btn1 = QPushButton(self)
self.btn1.setText('Send Msg')
self.btn1.move(100,75)
self.btn1.clicked.connect(send_message_to_client)

self.show()    
if __name__ == '__main__':
sio = socketio.Server(async_mode='eventlet')
def start_listening():
eventlet.wsgi.server(eventlet.listen(('', 5000)), serverapp)

@sio.event
def connect(sid, environ):
print('nConnected with SID', sid)
def send_message_to_client():
print('nSending from Button')
sio.emit('Message_from_server', {"Message 1": "Hello"})
@sio.event
def message_from_client(sid, data):
print('nThis message came from the Client.', data, 'n')
serverapp = socketio.WSGIApp(sio, static_files={'/': {'content_type': 'text/html', 'filename': 'index.html'}})
thread = Thread(target = start_listening, args=())
thread.start()
app = QApplication(sys.argv)
form = My_Class()
form.show()
sys.exit(app.exec_())
下面是客户端代码:
from PyQt5.QtWidgets import QPushButton, QDialog, QApplication
import socketio, sys
class My_Client(QDialog):
def __init__(self, parent=None):
super(My_Client, self).__init__(parent)

self.setWindowTitle("My SocketIO Clent")
self.resize(300,150)
self.move(700, 200)

self.btn1 = QPushButton(self)
self.btn1.setText('connect')
self.btn1.move(50,75)
self.btn1.clicked.connect(connect)
self.btn2 = QPushButton(self)
self.btn2.setText('Send Msg')
self.btn2.move(175,75)
self.btn2.clicked.connect(send_message_from_client)

self.show()    
if __name__ == '__main__':
sio = socketio.Client()
def connect():
sio.connect('http://localhost:5000')
print('nConnection established using SID', sio.sid)
@sio.event
def message_from_server(sid, data):
print('nMessage from server received with ', data)

def send_message_from_client():
print('nMessage sent from Client')
sio.emit('message_from_client', {'Message': 'Hello World'})
@sio.event
def disconnect():
print('nDisconnected from servern')
app = QApplication(sys.argv)
form = My_Client()
form.show()
sys.exit(app.exec_())

我正在使用socket。asyncServer和面临同样的问题。问题是我的服务器的pingTimeout太小(5秒)。pingTimeout是客户机在断开连接之前等待服务器响应的时间(以秒为单位),默认设置为5秒。将超时时间增加到60秒,为我解决了这个问题。在服务器代码中,更改

sio = socketio.Server(async_mode='eventlet')

到下面的

sio = socketio.Server(async_mode='eventlet', ping_timeout=60)

sio = socketio.AsyncServer(ping_timeout=60)

所以packet queue is empty, aborting是底层python工程包的产品,当发送空有效负载时触发,我相信当服务器和客户端之间正在进行的PING/PONG在服务器端错过时。

因此,看起来您正在处理的主要问题是客户端断开连接,因为服务器无法PONG返回到客户端,客户端最终放弃并断开连接。

所以最大的问题是为什么服务器不能将消息发送给客户端(但可以接收它们)。我想这与线程有关,无论是通过在线程中运行eventlet服务器,还是通过将sio函数传递给PyQt。我建议隔离独立于PyQt操作的连接,并尝试使用multiprocessing或直接运行服务器。

从python -socket问题来看,您似乎需要使用sio.wait。在#272和#922中有提到

你可以在examples/client的例子中看到它们:

Asyncio (examples/client/async) (link):

async def start_server():
await sio.connect('http://localhost:5000', auth={'token': 'my-token'})
await sio.wait()

if __name__ == '__main__':
asyncio.run(start_server())

Threads (examples/client/threads) (link):

if __name__ == '__main__':
sio.connect('http://localhost:5000', auth={'token': 'my-token'})
sio.wait()

所以,在你的例子中,它应该是:

if __name__ == '__main__':
sio = socketio.Client()
def connect():
sio.connect('http://localhost:5000')
print('nConnection established using SID', sio.sid)
# === Add wait ===
sio.wait()

我知道这个问题是很久以前的事了,但我这是我在谷歌上搜索错误信息时唯一出现的SO帖子。

花了很长时间为我解决这个问题。我只是希望在文档页中提到了这一点。

最新更新