客户端断开连接后如何重新连接?

时间:2020-08-14 07:11:09

标签: python python-3.x pyqt5

我编写了一个简单的客户端演示,客户端在服务器启动后需要重新连接到服务器,但是连接成功并出现错误?

server.py

from PyQt5.QtCore import *
from PyQt5.QtNetwork import *
from PyQt5.QtWidgets import *

class Server:
    def __init__(self):
        self.s = QTcpServer()
        self.s.listen(QHostAddress.LocalHost, 9978)
        self.s.newConnection.connect(self.on_new_connection)
        self.cnt = 0
    
    def on_new_connection(self):
        self.c = self.s.nextPendingConnection()
        self.c.readyRead.connect(self.on_read)
    
    def on_read(self):
        print('server:', self.c.readAll())
        self.cnt += 1
        self.c.write(bytes(str(self.cnt), encoding='utf-8'))

class ServerDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('server')
        self.server = Server()
        self.disBn = QPushButton('kick up', clicked=self.on_kick)
        
        layout = QVBoxLayout()
        layout.addWidget(self.disBn)
        
        self.setLayout(layout)
    
    def on_kick(self):
        # simulate server kick up client
        self.server.c.disconnectFromHost()

app = QApplication([])
s = ServerDemo()
s.resize(300, 200)
s.show()
app.exec()

client.py

from PyQt5.QtCore import *
from PyQt5.QtNetwork import *
from PyQt5.QtWidgets import *
import traceback
import time

class Client(QObject):
    def __init__(self):
        super().__init__()
        self.sock = QTcpSocket(self)
        self.sock.disconnected.connect(self.on_disc)
        self.sock.readyRead.connect(self.on_data)
    
    def on_data(self):
        data = self.sock.readAll()
        print('client:', data)
        
    def on_disc(self):
        print('reconnect')
        self.sock.close()
        self.sock.connectToHost(QHostAddress.LocalHost, 9978)
        print('login success')
        
    def sleep(self, v):
        loop = QEventLoop()
        QTimer.singleShot(v*1000, loop.quit)
        loop.exec()
        
    def do_work(self):
        self.sock.connectToHost(QHostAddress.LocalHost, 9978)
        for i in range(10000):
            # print(self.sock.state())
            self.sock.writeData(bytes(str(i), encoding='utf-8'))
            self.sleep(1)

class ClientDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Client')
        clientBn = QPushButton('start a thread', clicked=self.on_thread)
        
        layout = QVBoxLayout()
        layout.addWidget(clientBn)
        
        self.setLayout(layout)
    
    def on_thread(self):
        self.client_thread = QThread()
        self.worker = Client()
        self.worker.moveToThread(self.client_thread)
        self.client_thread.started.connect(self.worker.do_work)
        self.client_thread.start()

app = QApplication([])
demo = ClientDemo()
demo.resize(300, 200)
demo.show()
app.exec()

我首先运行server.py,然后运行client.py,然后启动要运行的线程。 然后启动客户端,客户端尝试重新连接。但显示错误如下。

reconnect
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x6cd4558), parent's thread is QThread(0x9583df0), current thread is QThread(0x131cfb8)
QObject::startTimer: Timers cannot be started from another thread
login success
QObject::killTimer: Timers cannot be stopped from another thread
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

1 个答案:

答案 0 :(得分:0)

我通过阅读很多文章成功解决了这个问题。
self.sock = QTcpSocket(self)更改为self.sock = QTcpSocket()

然后改变

    def on_thread(self):
        self.client_thread = QThread()
        self.worker = Client()
        self.worker.moveToThread(self.client_thread)
        self.client_thread.started.connect(self.worker.do_work)
        self.client_thread.start()

收件人

    def on_thread(self):
        self.client_thread = QThread()
        self.worker = Client()
        
        self.client_thread.started.connect(self.worker.do_work)
        self.worker.moveToThread(self.client_thread)
        self.client_thread.start()

备注:
QTcpSocket不能像在其他线程中那样使用,使用它有很多陷阱。
QTcpSocket很难跨越线程。