Ryan Xu
Ryan Xu

Reputation: 43

Socket server in PyQt5 freeze and crash

I have a simple PyQt window with a socket setup to listen on a port, and I also have a client that wants to send data to this server.

import time
import socket
from PyQT5.QTCore import QTimer

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.initUI()

    def initUI(self):

        ... UI stuff
        
        self.initSocket()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateData)
        self.timer.start(1000)

    def initSocket(self):
        binded = False
        while True:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            if not binded:
                try:
                    self.socket.bind(('localhost', 12345))
                    self.socket.listen(5)
                    binded = True
                    print("server binded")
                    break
                except Exception as e:
                    print(f"Error binding: {e}")
                    time.sleep(1)
 
    def updateData(self):
        print("starting update data")
        try:
            conn, addr = self.socket.accept()
            print("accepted connection from client")
            data = self.socket.recv(1024).decode()
            data_dict = json.loads(data)
        except Exception as e:
            print(f"Error updating data: {e}")

So far the UI is functional on its own. However after setting up sockets, the program would display the UI, print the "server binded", then the "starting update data", then the whole process would freeze and crash. Side note in case it matters, everything is all setup on a raspberry pi4, including the client program that the server is listening to.

Upvotes: 0

Views: 273

Answers (1)

Ryan Xu
Ryan Xu

Reputation: 43

I seem to have figured out my own solution, PyQTimer just crashes the program for some reason. To achieve the same effect, I ended up using a while loop inside updateData() and putting it on a new thread so it can loop in the background while the UI can work its own thing, instead of calling it again and again using QTimer as the interval. I also cleaned up the initSocket() and UpdateData() a little bit.

import time
import socket
import threading

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.initUI()

    def initUI(self):

        ... UI stuff
        
        self.initSocket()
        updateData_thread = threading.Thread(target=self.updateData)
        updateData_thread.start()

   def initSocket(self):
        host = 'localhost'
        port = 12345

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind((host, port))
        self.socket.listen(2)
        print(f"Listening on {host}:{port}")
        
 
    def updateData(self):
        while True:
            try:
                conn, addr = self.socket.accept()
                print(f"Connected to {addr}")
                data = conn.recv(1024).decode()
                data_dict = json.loads(data)
                ime.sleep(0.4)
                
            except Exception as e:
                print(f'Error: {str(e)}')
                conn.close()
                time.sleep(2)

Upvotes: 1

Related Questions