Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7554565
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T11:22:10+00:00 2026-05-30T11:22:10+00:00

I am looking to create a QTcpServer using PyQt that can simultaneously return data

  • 0

I am looking to create a QTcpServer using PyQt that can simultaneously return data to 2 or more clients. I assume that this will require threading.

Using the threadedfortuneserver.py example as a test case (included with PyQt4, on my system it is found in /usr/share/doc/python-qt4-doc/examples/network), I want to connect multiple clients and each time one of the clients asks for a fortune, the other clients also get updated with a message like “Client X just received the fortune ‘blah blah blah'”.

I understand how the fortuneserver/client program works, but it seems that the client connections are immediately terminated after the fortune is sent back to the client. My specific questions are:

  1. Is it possible to keep all of the connections open so that every
    time one of the clients requests a fortune, the other clients can be
    updated?

  2. If so, what is the best way to keep track of and loop over the connected clients?

This is a serious stumbling block for me because I want to develop an app where several clients can interact, and each client can be updated about the actions of the other clients.

Thanks in advance for your help, let me know if there is any other information I can provide.

I found this thread but there wasn’t enough specific information to make use of. Other discussions have been for the Python socket package, but it is my understanding that when using PyQt, the server should be a QTcpServer so everything plays nice.

*** EDIT ***

Here are the beginning stages of my solution. I have created a basic server and client. The server just sends back what the client entered into a Line Edit box.

I am basing this on the “buildingservices” example from Chapter 18 of Rapid GUI Programming with Python and Qt.

The major change I made is that now the threads keep running indefinitely and their sockets stay open, listening for data being sent by the client.

It handles multiple clients fine. It is certainly ugly, but I think it is a good starting point.

What I would like is to be able to notify each client whenever one client enters text (like a typical chat program, say).

Also, to give you an idea of who you are dealing with, I am NOT a professional programmer. I am a physicist with many years of undisciplined scripting and fiddling around under my belt. But I would like to try to develop basic server/client programs that can pass data around.

Thanks for any help or suggestions!

SERVER:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *

PORT = 9999
SIZEOF_UINT16 = 2

class Thread(QThread):

    #lock = QReadWriteLock()

    def __init__(self, socketId, parent):
        super(Thread, self).__init__(parent)
        self.socketId = socketId

    def run(self):
        self.socket = QTcpSocket()

        if not self.socket.setSocketDescriptor(self.socketId):
            self.emit(SIGNAL("error(int)"), socket.error())
            return

        while self.socket.state() == QAbstractSocket.ConnectedState:
            nextBlockSize = 0
            stream = QDataStream(self.socket)
            stream.setVersion(QDataStream.Qt_4_2)
            if (self.socket.waitForReadyRead(-1) and
                self.socket.bytesAvailable() >= SIZEOF_UINT16):
                nextBlockSize = stream.readUInt16()
            else:
                self.sendError("Cannot read client request")
                return
            if self.socket.bytesAvailable() < nextBlockSize:
                if (not self.socket.waitForReadyRead(-1) or
                    self.socket.bytesAvailable() < nextBlockSize):
                    self.sendError("Cannot read client data")
                    return

            textFromClient = stream.readQString()

            textToClient = "You wrote: \"{}\"".format(textFromClient)
            self.sendReply(textToClient)

    def sendError(self, msg):
        reply = QByteArray()
        stream = QDataStream(reply, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_2)
        stream.writeUInt16(0)
        stream.writeQString("ERROR")
        stream.writeQString(msg)
        stream.device().seek(0)
        stream.writeUInt16(reply.size() - SIZEOF_UINT16)
        self.socket.write(reply)

    def sendReply(self, text):
        reply = QByteArray()
        stream = QDataStream(reply, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_2)
        stream.writeUInt16(0)
        stream.writeQString(text)
        stream.device().seek(0)
        stream.writeUInt16(reply.size() - SIZEOF_UINT16)
        self.socket.write(reply)


class TcpServer(QTcpServer):

    def __init__(self, parent=None):
        super(TcpServer, self).__init__(parent)

    def incomingConnection(self, socketId):
        self.thread = Thread(socketId, self)
        self.thread.start()


class ServerDlg(QPushButton):

    def __init__(self, parent=None):
        super(ServerDlg, self).__init__(
                "&Close Server", parent)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        self.tcpServer = TcpServer(self)
        if not self.tcpServer.listen(QHostAddress("0.0.0.0"), PORT):
            QMessageBox.critical(self, "Threaded Server",
                    "Failed to start server: {}".format(
                    self.tcpServer.errorString()))
            self.close()
            return

        self.connect(self, SIGNAL("clicked()"), self.close)
        font = self.font()
        font.setPointSize(24)
        self.setFont(font)
        self.setWindowTitle("Threaded Server")

app = QApplication(sys.argv)
form = ServerDlg()
form.show()
form.move(0, 0)
app.exec_()

CLIENT:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *

PORT = 9999
SIZEOF_UINT16 = 2

class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        # Ititialize socket
        self.socket = QTcpSocket()
        # Initialize data IO variables
        self.nextBlockSize = 0
        self.request = None
        # Create widgets/layout
        self.browser = QTextBrowser()
        self.lineedit = QLineEdit("Texty bits")
        self.lineedit.selectAll()
        self.connectButton = QPushButton("Connect")
        self.connectButton.setDefault(False)
        self.connectButton.setEnabled(True)
        layout = QVBoxLayout()
        layout.addWidget(self.browser)
        layout.addWidget(self.lineedit)
        layout.addWidget(self.connectButton)
        self.setLayout(layout)
        self.lineedit.setFocus()

        # Signals and slots for line edit and connect button
        self.lineedit.returnPressed.connect(self.sendToServer)
        self.connectButton.released.connect(self.connectToServer)

        self.setWindowTitle("Client")

        # Signals and slots for networking
        self.socket.readyRead.connect(self.readFromServer)
        self.socket.disconnected.connect(self.serverHasStopped)
        self.connect(self.socket,
                     SIGNAL("error(QAbstractSocket::SocketError)"),
                     self.serverHasError)

    # Update GUI
    def updateUi(self, text):
        self.browser.append(text)

    # Create connection to server
    def connectToServer(self):
        self.connectButton.setEnabled(False)
        print("Connecting to server")
        self.socket.connectToHost("localhost", PORT)

    # Send data to server
    def sendToServer(self):
        self.request = QByteArray()
        stream = QDataStream(self.request, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_2)
        stream.writeUInt16(0)
        stream.writeQString(self.lineedit.text())
        stream.device().seek(0)
        stream.writeUInt16(self.request.size() - SIZEOF_UINT16)
        self.socket.write(self.request)
        self.nextBlockSize = 0
        self.request = None
        self.lineedit.setText("")

    # Read data from server and update Text Browser
    def readFromServer(self):
        stream = QDataStream(self.socket)
        stream.setVersion(QDataStream.Qt_4_2)

        while True:
            if self.nextBlockSize == 0:
                if self.socket.bytesAvailable() < SIZEOF_UINT16:
                    break
                self.nextBlockSize = stream.readUInt16()
            if self.socket.bytesAvailable() < self.nextBlockSize:
                break
            textFromServer = stream.readQString()
            self.updateUi(textFromServer)
            self.nextBlockSize = 0

    def serverHasStopped(self):
        self.socket.close()

    def serverHasError(self):
        self.updateUi("Error: {}".format(
                self.socket.errorString()))
        self.socket.close()


app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T11:22:12+00:00Added an answer on May 30, 2026 at 11:22 am

    As was probably exasperatingly obvious to most of you, I didn’t fully understand how to deal with threads! Not to worry, I have discovered a way to design a server that can send data to multiple clients with nary a secondary thread to be found.

    Quite simple, really, but I’m not the quickest of cats at the best of times.

    SERVER:

    #!/usr/bin/env python3
    
    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from PyQt4.QtNetwork import *
    
    PORT = 9999
    SIZEOF_UINT32 = 4
    
    class ServerDlg(QPushButton):
    
        def __init__(self, parent=None):
            super(ServerDlg, self).__init__(
                    "&Close Server", parent)
            self.setWindowFlags(Qt.WindowStaysOnTopHint)
    
            self.tcpServer = QTcpServer(self)               
            self.tcpServer.listen(QHostAddress("0.0.0.0"), PORT)
            self.connect(self.tcpServer, SIGNAL("newConnection()"), 
                        self.addConnection)
            self.connections = []
    
            self.connect(self, SIGNAL("clicked()"), self.close)
            font = self.font()
            font.setPointSize(24)
            self.setFont(font)
            self.setWindowTitle("Server")
    
        def addConnection(self):
            clientConnection = self.tcpServer.nextPendingConnection()
            clientConnection.nextBlockSize = 0
            self.connections.append(clientConnection)
    
            self.connect(clientConnection, SIGNAL("readyRead()"), 
                    self.receiveMessage)
            self.connect(clientConnection, SIGNAL("disconnected()"), 
                    self.removeConnection)
            self.connect(clientConnection, SIGNAL("error()"), 
                    self.socketError)
    
        def receiveMessage(self):
            for s in self.connections:
                if s.bytesAvailable() > 0:
                    stream = QDataStream(s)
                    stream.setVersion(QDataStream.Qt_4_2)
    
                    if s.nextBlockSize == 0:
                        if s.bytesAvailable() < SIZEOF_UINT32:
                            return
                        s.nextBlockSize = stream.readUInt32()
                    if s.bytesAvailable() < s.nextBlockSize:
                        return
    
                    textFromClient = stream.readQString()
                    s.nextBlockSize = 0
                    self.sendMessage(textFromClient, 
                                     s.socketDescriptor())
                    s.nextBlockSize = 0
    
        def sendMessage(self, text, socketId):
            for s in self.connections:
                if s.socketDescriptor() == socketId:
                    message = "You> {}".format(text)
                else:
                    message = "{}> {}".format(socketId, text)
                reply = QByteArray()
                stream = QDataStream(reply, QIODevice.WriteOnly)
                stream.setVersion(QDataStream.Qt_4_2)
                stream.writeUInt32(0)
                stream.writeQString(message)
                stream.device().seek(0)
                stream.writeUInt32(reply.size() - SIZEOF_UINT32)
                s.write(reply)
    
        def removeConnection(self):
            pass
    
        def socketError(self):
            pass
    
    
    app = QApplication(sys.argv)
    form = ServerDlg()
    form.show()
    form.move(0, 0)
    app.exec_()
    

    CLIENT

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from PyQt4.QtNetwork import *
    
    PORTS = (9998, 9999)
    PORT = 9999
    SIZEOF_UINT32 = 4
    
    class Form(QDialog):
    
        def __init__(self, parent=None):
            super(Form, self).__init__(parent)
    
            # Ititialize socket
            self.socket = QTcpSocket()
    
            # Initialize data IO variables
            self.nextBlockSize = 0
            self.request = None
    
            # Create widgets/layout
            self.browser = QTextBrowser()
            self.lineedit = QLineEdit("Enter text here, dummy")
            self.lineedit.selectAll()
            self.connectButton = QPushButton("Connect")
            self.connectButton.setEnabled(True)
            layout = QVBoxLayout()
            layout.addWidget(self.browser)
            layout.addWidget(self.lineedit)
            layout.addWidget(self.connectButton)
            self.setLayout(layout)
            self.lineedit.setFocus()
    
            # Signals and slots for line edit and connect button
            self.lineedit.returnPressed.connect(self.issueRequest)
            self.connectButton.clicked.connect(self.connectToServer)
    
            self.setWindowTitle("Client")
            # Signals and slots for networking
            self.socket.readyRead.connect(self.readFromServer)
            self.socket.disconnected.connect(self.serverHasStopped)
            self.connect(self.socket,
                         SIGNAL("error(QAbstractSocket::SocketError)"),
                         self.serverHasError)
    
        # Update GUI
        def updateUi(self, text):
            self.browser.append(text)
    
        # Create connection to server
        def connectToServer(self):
            self.connectButton.setEnabled(False)
            self.socket.connectToHost("localhost", PORT)
    
        def issueRequest(self):
            self.request = QByteArray()
            stream = QDataStream(self.request, QIODevice.WriteOnly)
            stream.setVersion(QDataStream.Qt_4_2)
            stream.writeUInt32(0)
            stream.writeQString(self.lineedit.text())
            stream.device().seek(0)
            stream.writeUInt32(self.request.size() - SIZEOF_UINT32)
            self.socket.write(self.request)
            self.nextBlockSize = 0
            self.request = None
            self.lineedit.setText("")
    
        def readFromServer(self):
            stream = QDataStream(self.socket)
            stream.setVersion(QDataStream.Qt_4_2)
    
            while True:
                if self.nextBlockSize == 0:
                    if self.socket.bytesAvailable() < SIZEOF_UINT32:
                        break
                    self.nextBlockSize = stream.readUInt32()
                if self.socket.bytesAvailable() < self.nextBlockSize:
                    break
                textFromServer = stream.readQString()
                self.updateUi(textFromServer)
                self.nextBlockSize = 0
    
        def serverHasStopped(self):
            self.socket.close()
            self.connectButton.setEnabled(True)
    
        def serverHasError(self):
            self.updateUi("Error: {}".format(
                    self.socket.errorString()))
            self.socket.close()
            self.connectButton.setEnabled(True)
    
    
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    app.exec_()
    

    To summarize, each client connection opens a socket, and the socket is appended to a list of all client sockets. Then, when one of the clients sends text, the server loops over the client sockets, finds the one that has bytesAvailable, reads it in, and then sends the message to the other clients.

    I would be curious to hear what other people may think of this approach. Pitfalls, issues, etc.

    Thanks!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm looking to create a singleton in Delphi. I've done this before using older
I am looking to create a web widget that can be easily integrated into
I'm looking to create a reusable function that will generate a random key with
I'm looking to create a windows application in vb.net or c#.net that will capture
Im looking to create a site that will attach a piece of media to
Im looking to create a custom ASP.NET container control that will allow me to
I'm looking to create a cocoa program that simply sends data typed into text
I am looking to create a web part that will get the value of
I am looking to create a function in Java that will take in two
Looking to create a hash table from a text output that looks like this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.