I want create a websocket client by using QWebSocket in PyQt5.For convenience, assume I have a websocket server, source code is like this ,
from PyQt5 import QtCore, QtWebSockets, QtNetwork, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QAction
from PyQt5.QtCore import QUrl
class MyServer(QtCore.QObject):
def __init__(self, parent):
super(QtCore.QObject, self).__init__(parent)
self.clients = []
self.server = QtWebSockets.QWebSocketServer(parent.serverName(), parent.secureMode(), parent)
if self.server.listen(QtNetwork.QHostAddress.LocalHost, 1302):
print('Connected: '+self.server.serverName()+' : '
+self.server.serverAddress().toString()+':'+str(self.server.serverPort()))
else:
print('error')
self.server.newConnection.connect(self.onNewConnection)
self.clientConnection = None
print(self.server.isListening())
def onNewConnection(self):
self.clientConnection = self.server.nextPendingConnection()
self.clientConnection.textMessageReceived.connect(self.processTextMessage)
self.clientConnection.binaryMessageReceived.connect(self.processBinaryMessage)
self.clientConnection.disconnected.connect(self.socketDisconnected)
print("newClient")
self.clients.append(self.clientConnection)
def processTextMessage(self, message):
print(message)
if self.clientConnection:
for client in self.clients:
# if client!= self.clientConnection:
client.sendTextMessage(message)
# self.clientConnection.sendTextMessage(message)
def processBinaryMessage(self, message):
print("b:",message)
if self.clientConnection:
self.clientConnection.sendBinaryMessage(message)
def socketDisconnected(self):
if self.clientConnection:
self.clients.remove(self.clientConnection)
self.clientConnection.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_()
It can create a websocket server,and I test it by using JavaScript,it works fine .But I can find a way to create a client by using Qwebsocket.My client code is like this:
client = QtWebSockets.QWebSocket("",QtWebSockets.QWebSocketProtocol.Version13,None)
client.open(QUrl("ws://127.0.0.1:1302"))
client.sendTextMessage("asd")
client.close()
It seems the server did not receive the message sent by client,how to create a websocket client and send message by using Qwebsocket?
This is a typical problem with qt console programs, you need to call your client methods outside of the python constructor (__init__
).
I modified your server a little bit, adding some error tests (nothing really new):
from PyQt5 import QtCore, QtWebSockets, QtNetwork, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QAction
from PyQt5.QtCore import QUrl
class MyServer(QtCore.QObject):
def __init__(self, parent):
super(QtCore.QObject, self).__init__(parent)
self.clients = []
print("server name: {}".format(parent.serverName()))
self.server = QtWebSockets.QWebSocketServer(parent.serverName(), parent.secureMode(), parent)
if self.server.listen(QtNetwork.QHostAddress.LocalHost, 1302):
print('Listening: {}:{}:{}'.format(
self.server.serverName(), self.server.serverAddress().toString(),
str(self.server.serverPort())))
else:
print('error')
self.server.acceptError.connect(self.onAcceptError)
self.server.newConnection.connect(self.onNewConnection)
self.clientConnection = None
print(self.server.isListening())
def onAcceptError(accept_error):
print("Accept Error: {}".format(accept_error))
def onNewConnection(self):
print("onNewConnection")
self.clientConnection = self.server.nextPendingConnection()
self.clientConnection.textMessageReceived.connect(self.processTextMessage)
self.clientConnection.textFrameReceived.connect(self.processTextFrame)
self.clientConnection.binaryMessageReceived.connect(self.processBinaryMessage)
self.clientConnection.disconnected.connect(self.socketDisconnected)
print("newClient")
self.clients.append(self.clientConnection)
def processTextFrame(self, frame, is_last_frame):
print("in processTextFrame")
print("\tFrame: {} ; is_last_frame: {}".format(frame, is_last_frame))
def processTextMessage(self, message):
print("processTextMessage - message: {}".format(message))
if self.clientConnection:
for client in self.clients:
# if client!= self.clientConnection:
client.sendTextMessage(message)
# self.clientConnection.sendTextMessage(message)
def processBinaryMessage(self, message):
print("b:",message)
if self.clientConnection:
self.clientConnection.sendBinaryMessage(message)
def socketDisconnected(self):
print("socketDisconnected")
if self.clientConnection:
self.clients.remove(self.clientConnection)
self.clientConnection.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_()
The client uses some QTimer
to call the required methods outside of the __init__
method. I also added ping / pong methods to check the connection :
import sys
from PyQt5 import QtCore, QtWebSockets, QtNetwork
from PyQt5.QtCore import QUrl, QCoreApplication, QTimer
from PyQt5.QtWidgets import QApplication
class Client(QtCore.QObject):
def __init__(self, parent):
super().__init__(parent)
self.client = QtWebSockets.QWebSocket("",QtWebSockets.QWebSocketProtocol.Version13,None)
self.client.error.connect(self.error)
self.client.open(QUrl("ws://127.0.0.1:1302"))
self.client.pong.connect(self.onPong)
def do_ping(self):
print("client: do_ping")
self.client.ping(b"foo")
def send_message(self):
print("client: send_message")
self.client.sendTextMessage("asd")
def onPong(self, elapsedTime, payload):
print("onPong - time: {} ; payload: {}".format(elapsedTime, payload))
def error(self, error_code):
print("error code: {}".format(error_code))
print(self.client.errorString())
def close(self):
self.client.close()
def quit_app():
print("timer timeout - exiting")
QCoreApplication.quit()
def ping():
client.do_ping()
def send_message():
client.send_message()
if __name__ == '__main__':
global client
app = QApplication(sys.argv)
QTimer.singleShot(2000, ping)
QTimer.singleShot(3000, send_message)
QTimer.singleShot(5000, quit_app)
client = Client(app)
app.exec_()
Server output:
G:\Qt\QtTests>python so_qwebsocket_server.py
server name: My Socket
Listening: My Socket:127.0.0.1:1302
True
onNewConnection
newClient
in processTextFrame
Frame: asd ; is_last_frame: True
processTextMessage - message: asd
socketDisconnected
client output:
G:\Qt\QtTests>python so_qwebsocket_client.py
client: do_ping
onPong - time: 0 ; payload: b'foo'
client: send_message
timer timeout
All in all, if you use your client in a simple GUI (e.g. moving the client.sendTextMessage()
outside __init__
and connecting a button click to actually send the message), due to its asynchronous nature, it should work without any problems!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With