The problem: 我想让客户端重试连接,如果服务器不能通过发送ping/文本消息使用qTimer. 客户端期望从服务器收到PONG/Text消息以开始处理某些数据.

服务器在前20秒不侦听传入连接的情况下启动,以模拟连接问题,20秒后,我将服务器设置为侦听,以便它可以接受传入连接.

如果客户端在第一次try 时无法连接到服务器,或者在没有监听的20秒时间内,即使服务器稍后开始监听,它也不会连接,但是如果我在服务器切换到监听状态时运行客户端,一切都会正常工作.我如何才能修复它,以便客户端实际上将发送ping/文本消息,因为现在它看起来像是进入了一个循环,这阻止了它发送ping/文本消息.

客户端部分:

from time import sleep
import sys
from PySide6 import QtCore, QtWebSockets
from PySide6.QtCore import QUrl, QTimer
from PySide6.QtWidgets import QApplication


class Client(QtCore.QObject):
    def __init__(self, parent):
        super().__init__(parent)

        self.client = QtWebSockets.QWebSocket("", QtWebSockets.QWebSocketProtocol.Version13, None)
        self.client.open(QUrl("ws://127.0.0.1:6000"))
        self.client.textMessageReceived.connect(self.process_message)
        self.client.pong.connect(self.get_pong)
        # self.client.error.connect(self.error)

        self.date_list = ['2000-01-01']

        self.check_status_timer = QTimer()
        self.check_status_timer.timeout.connect(self.send_ping)
        self.check_status_timer.start(2000)

    # some data processing after connection established
    def process(self, day):
        print(f"Day {day}")
        for i in range(10):
            print(f"Sleeping {9 - i}")
            sleep(.5)
        print("emitted")
        return True

    def create_and_run(self):
        current_date = self.date_list[0]
        result = self.process(current_date)
        if result:
            self.send_message()
        else:
            print("PROCESS FAILED")

    def process_message(self, message):
        if message == "ping" or message == "True":
            self.check_status_timer.stop()
            self.create_and_run()

    def get_pong(self):
        print("PONG")

    def send_ping(self):
        print("SENDING PING")
        self.client.ping()
        self.client.sendTextMessage("ping")

    def send_message(self):
        self.client.sendTextMessage("Client0")

    def error(self, error_code):
        print("error code: {}".format(error_code))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    client = Client(app)
    app.exec()

服务器部件

from PySide6 import QtCore, QtWebSockets, QtNetwork
from PySide6.QtWidgets import QApplication


class MyServer(QtCore.QObject):
    def __init__(self, parent):
        super().__init__(parent)
        self.clients = []
        self.server = QtWebSockets.QWebSocketServer(parent.serverName(), parent.secureMode(), parent)
        self.server.acceptError.connect(self.on_accept_error)
        self.server.newConnection.connect(self.on_new_connection)
        
        # create timer so server will switch to listening state later
        self.count = 0
        self.timer_listen = QtCore.QTimer()
        self.timer_listen.timeout.connect(self.make_listen)
        self.timer_listen.start(2000)
    
    def make_listen(self):
        if self.count >= 10:
            self.timer_listen.stop()
            self.server.listen(QtNetwork.QHostAddress.LocalHost, 6000)
            print(self.count, self.server.isListening())
        else:
            print(self.count, self.server.isListening())
            self.count += 1

    def on_accept_error(accept_error):
        print("Accept Error: {}".format(accept_error))

    def on_new_connection(self):
        client_connection = self.server.nextPendingConnection()
        client_connection.textMessageReceived.connect(self.process_message)
        client_connection.disconnected.connect(self.disconnect)
        self.clients.append(client_connection)

    def process_message(self, message):
        print(message)
        if message == "ping":
            self.sender().sendTextMessage("ping")

    def disconnect(self):
        if self.sender() in self.clients:
            self.clients.remove(self.sender())
            self.sender().deleteLater()


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    serverObject = QtWebSockets.QWebSocketServer('My Socket', QtWebSockets.QWebSocketServer.NonSecureMode)
    server = MyServer(serverObject)
    serverObject.closed.connect(app.quit)
    app.exec()

我试图利用Worker类来防止客户端的主循环冻结,并且我试图子类QWebSocket,但没有成功.

推荐答案

根据comment sectionekhumoro提供的解决方案

from time import sleep
import sys
from PySide6 import QtCore, QtWebSockets
from PySide6.QtCore import QUrl, QTimer
from PySide6.QtWidgets import QApplication
from PySide6.QtNetwork import QAbstractSocket

class Client(QtCore.QObject):
    def __init__(self, parent):
        super().__init__(parent)

        self.client = QtWebSockets.QWebSocket("", QtWebSockets.QWebSocketProtocol.Version13, None)

        self.client.textMessageReceived.connect(self.process_message)
        self.client.pong.connect(self.get_pong)
        # self.client.error.connect(self.error)

        self.date_list = ['2000-01-01']

        self.check_status_timer = QTimer()
        self.check_status_timer.timeout.connect(self.send_ping)
        self.check_status_timer.start(2000)

    def process(self, day):
        print(f"Day {day}")
        for i in range(10):
            print(f"Sleeping {9 - i}")
            sleep(.5)
        print("emitted")
        return True

    def create_and_run(self):
        current_date = self.date_list[0]
        result = self.process(current_date)
        if result:
            self.send_message()
        else:
            print("PROCESS FAILED")

    def process_message(self, message):
        if message == "ping" or message == "True":
            self.check_status_timer.stop()
            self.create_and_run()

    def get_pong(self):
        print("PONG")

    def send_ping(self):
        print("SENDING PING")
        if self.client.state() == QAbstractSocket.SocketState.ConnectedState:
            self.client.ping()
            self.client.sendTextMessage("ping")
        else:
            self.client.open(QUrl("ws://127.0.0.1:6000"))


    def send_message(self):
        self.client.sendTextMessage("Client0")

    def error(self, error_code):
        print("error code: {}".format(error_code))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    client = Client(app)
    app.exec()

Python相关问答推荐

配置Sweetviz以分析对象类型列,而无需转换

为什么tkinter框架没有被隐藏?

max_of_three使用First_select、second_select、

使用miniconda创建环境的问题

对于一个给定的数字,找出一个整数的最小和最大可能的和

按列分区,按另一列排序

使用groupby Pandas的一些操作

"使用odbc_connect(raw)连接字符串登录失败;可用于pyodbc"

Python解析整数格式说明符的规则?

将tdqm与cx.Oracle查询集成

无法连接到Keycloat服务器

当条件满足时停止ODE集成?

Pandas—堆栈多索引头,但不包括第一列

Python如何导入类的实例

SpaCy:Regex模式在基于规则的匹配器中不起作用

为什么Visual Studio Code说我的代码在使用Pandas concat函数后无法访问?

无法在盐流道中获得柱子

多索引数据帧到标准索引DF

如何将列表从a迭代到z-以抓取数据并将其转换为DataFrame?

如何通过特定导入在类中执行Python代码