You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一网络下Python PyQt Socket服务端与客户端连接失败问题

PyQt TCP服务端-客户端连接失败问题修复

问题分析

你的代码存在几个关键问题导致连接失败或通信异常:

  • 服务端未检查listen()调用是否成功,无法确认端口绑定、IP配置是否正常
  • 客户端未监听连接状态信号,无法排查连接失败原因(如网络不通、端口被占用)
  • 服务端发送消息时未确保client_socket已初始化,无连接时点击发送会崩溃
  • 发送数据后未调用flush(),PyQt的TCP套接字会缓冲数据,导致对方无法及时接收
  • 服务端固定绑定192.168.6.66,若该IP并非服务端当前活跃网卡IP,会导致监听失败

修复后的代码

server.py

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QPushButton, QLineEdit
from PyQt5.QtNetwork import QTcpServer, QHostAddress, QTcpSocket

class Server(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(500, 300)
        self.server = QTcpServer(self)
        self.client_socket = None  # 初始化客户端套接字为None

        # 监听所有网卡的12345端口,替代固定IP,避免IP绑定失败
        if not self.server.listen(QHostAddress.Any, 12345):
            self.log(f"Server start failed: {self.server.errorString()}")
        else:
            self.log(f"Server started, listening on port 12345")
        self.server.newConnection.connect(self.handle_client_connection)

        # UI组件初始化
        self.text_edit = QTextEdit(self)
        self.text_edit.setReadOnly(True)
        self.text_edit.setGeometry(10, 10, 400, 200)

        self.message_input = QLineEdit(self)
        self.message_input.setGeometry(10, 220, 200, 30)

        self.send_button = QPushButton("Send Message", self)
        self.send_button.setGeometry(220, 220, 200, 30)
        self.send_button.clicked.connect(self.send_message)

        self.setWindowTitle("Server")

    def send_message(self):
        if not self.client_socket or self.client_socket.state() != QTcpSocket.ConnectedState:
            self.log("No client connected, cannot send message")
            return
        message = self.message_input.text()
        if not message:
            return
        self.message_input.clear()
        self.client_socket.write(message.encode("utf-8"))
        self.client_socket.flush()  # 强制发送缓冲数据
        self.log(f"Sent message: {message}")

    def log(self, text):
        self.text_edit.append(text)

    def handle_client_connection(self):
        self.client_socket = self.server.nextPendingConnection()
        if not self.client_socket:
            return
        self.log(f"Client connected from {self.client_socket.peerAddress().toString()}")
        self.client_socket.readyRead.connect(self.receive_message)
        self.client_socket.disconnected.connect(self.handle_client_disconnect)

    def receive_message(self):
        client_socket = self.sender()
        if not client_socket:
            return
        data = client_socket.readAll().data().decode("utf-8")
        self.log(f"Received message: {data}")

    def handle_client_disconnect(self):
        self.log("Client disconnected")
        self.client_socket = None

if __name__ == "__main__":
    app = QApplication(sys.argv)
    server = Server()
    server.show()
    sys.exit(app.exec_())

client.py

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QPushButton, QLineEdit
from PyQt5.QtNetwork import QTcpSocket, QHostAddress

IP = '192.168.6.66'  # 替换为服务端实际IP

class Client(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(500, 300)
        self.client_socket = QTcpSocket(self)
        # 监听连接相关信号,排查连接状态
        self.client_socket.connected.connect(self.on_connected)
        self.client_socket.disconnected.connect(self.on_disconnected)
        self.client_socket.errorOccurred.connect(self.on_error)
        self.client_socket.readyRead.connect(self.receive_message)

        # 发起连接
        self.client_socket.connectToHost(QHostAddress(IP), 12345)

        # UI组件初始化
        self.text_edit = QTextEdit(self)
        self.text_edit.setReadOnly(True)
        self.text_edit.setGeometry(10, 10, 400, 200)

        self.message_input = QLineEdit(self)
        self.message_input.setGeometry(10, 220, 200, 30)

        self.send_button = QPushButton("Send Message", self)
        self.send_button.setGeometry(220, 220, 200, 30)
        self.send_button.clicked.connect(self.send_message)

        self.setWindowTitle("Client")

    def send_message(self):
        if self.client_socket.state() != QTcpSocket.ConnectedState:
            self.log("Not connected to server, cannot send message")
            return
        message = self.message_input.text()
        if not message:
            return
        self.message_input.clear()
        self.client_socket.write(message.encode("utf-8"))
        self.client_socket.flush()  # 强制发送缓冲数据
        self.log(f"Sent message: {message}")

    def log(self, text):
        self.text_edit.append(text)

    def receive_message(self):
        data = self.client_socket.readAll().data().decode("utf-8")
        self.log(f"Received message: {data}")

    def on_connected(self):
        self.log(f"Connected to server {IP}:12345")

    def on_disconnected(self):
        self.log("Disconnected from server")

    def on_error(self, error):
        self.log(f"Connection error: {self.client_socket.errorString()}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    client = Client()
    client.show()
    sys.exit(app.exec_())

关键修复点说明

  • 服务端改用QHostAddress.Any监听所有网卡,避免固定IP绑定失败
  • 增加连接状态检查和错误日志输出,方便排查问题
  • 发送数据后调用flush()确保数据立即发送
  • 服务端处理客户端断开连接的情况,避免无效套接字残留
  • 客户端监听connected、disconnected、errorOccurred信号,明确连接状态

内容的提问来源于stack exchange,提问作者Mohammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:17:32