实用指南:【Qt】 TCP套接字通信学习文档

【Qt】TCP套接字通信学习文档

一、概述

1.1 标准C++与Qt在网络编程上的区别

特性标准C++Qt框架
套接字支持无内置类,需使用操作系统C API提供QTcpServerQTcpSocket等类
开发复杂度较高,需要处理平台差异较低,跨平台API统一
编程范式面向过程/手动封装面向对象,信号槽机制
内存管理手动管理父子对象机制自动管理
异步处理需要多线程/select/poll等信号槽机制简化异步处理

1.2 Qt网络编程优势 ✨

  • 跨平台性:一次编写,多平台运行(Windows、Linux、macOS等)
  • 信号槽机制:事件驱动,避免阻塞式编程
  • 简化开发:封装底层细节,提供高级API
  • 集成度高:与Qt GUI、数据库等模块无缝集成
  • 内存安全:父子对象机制减少内存泄漏风险

二、核心类详解

2.1 QTcpServer - 服务器类

主要功能
  • 监听客户端连接请求
  • 建立与客户端的连接
  • 管理客户端连接队列
️ 常用API函数

构造函数

QTcpServer::QTcpServer(QObject *parent = nullptr);

监听绑定

bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any,
quint16 port = 0);

参数说明:

  • address:监听地址
    • QHostAddress::Any:IPv4任意地址(0.0.0.0)
    • QHostAddress::AnyIPv6:IPv6任意地址
    • QHostAddress::LocalHost:本地环回(127.0.0.1)
  • port:端口号,0表示自动分配可用端口

状态查询

bool QTcpServer::isListening() const;              // 是否正在监听
QHostAddress QTcpServer::serverAddress() const;    // 服务器绑定地址
quint16 QTcpServer::serverPort() const;            // 服务器绑定端口

连接管理

QTcpSocket *QTcpServer::nextPendingConnection();   // 获取待处理的连接
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = nullptr);
重要信号
void newConnection();  // 有新客户端连接时触发
void acceptError(QAbstractSocket::SocketError socketError);  // 接受连接出错时触发

2.2 QTcpSocket - 通信套接字类

继承关系
QObject → QIODevice → QAbstractSocket → QTcpSocket
️ 常用API函数

构造函数

QTcpSocket::QTcpSocket(QObject *parent = nullptr);

连接服务器

void connectToHost(const QString &hostName, quint16 port,
QIODevice::OpenMode openMode = QIODevice::ReadWrite);
void connectToHost(const QHostAddress &address, quint16 port,
QIODevice::OpenMode openMode = QIODevice::ReadWrite);

数据读写操作

// 读取数据
qint64 read(char *data, qint64 maxSize);     // 读取到指定缓冲区
QByteArray read(qint64 maxSize);             // 读取指定字节数
QByteArray readAll();                        // 读取所有可用数据
QByteArray readLine(qint64 maxSize = 0);     // 读取一行数据
// 写入数据
qint64 write(const char *data, qint64 maxSize);
qint64 write(const char *data);
qint64 write(const QByteArray &byteArray);
// 数据缓冲区操作
qint64 bytesAvailable() const;               // 可读字节数
qint64 bytesToWrite() const;                 // 等待写入的字节数
bool waitForBytesWritten(int msecs = 30000); // 等待数据写入完成
bool waitForReadyRead(int msecs = 30000);    // 等待可读数据

连接状态

bool isOpen() const;                         // 套接字是否打开
bool isReadable() const;                     // 是否可读
bool isWritable() const;                     // 是否可写
void close();                                // 关闭套接字
重要信号
void readyRead();                            // 有数据可读时触发
void connected();                            // 连接建立成功时触发
void disconnected();                         // 连接断开时触发
void bytesWritten(qint64 bytes);             // 数据写入完成时触发
void errorOccurred(QAbstractSocket::SocketError socketError);  // 错误发生时触发
void stateChanged(QAbstractSocket::SocketState socketState);   // 状态改变时触发

三、TCP通信流程

3.1 服务器端完整流程

通信流程步骤
  1. 创建QTcpServer对象 - 实例化服务器对象
  2. 启动监听 - 调用listen()方法绑定地址和端口
  3. 处理新连接 - 连接newConnection信号,在槽函数中处理
  4. 获取通信套接字 - 使用nextPendingConnection()获取客户端套接字
  5. 数据通信 - 通过客户端套接字进行读写操作
  6. 连接管理 - 处理连接断开和异常情况
流程图示
创建QTcpServer
listen绑定地址端口
连接newConnection信号
客户端连接触发信号
nextPendingConnection获取QTcpSocket
连接readyRead信号读取数据
使用write发送数据
处理disconnected信号清理资源

3.2 客户端完整流程

通信流程步骤
  1. 创建QTcpSocket对象 - 实例化客户端套接字
  2. 连接服务器 - 调用connectToHost()连接服务器
  3. 处理连接状态 - 连接connecteddisconnected信号
  4. 数据通信 - 连接readyRead信号读取数据,使用write()发送数据
  5. 断开连接 - 调用close()或处理服务器断开
流程图示
创建QTcpSocket
connectToHost连接服务器
connected信号确认连接
连接readyRead信号读取数据
使用write发送数据
处理disconnected信号
close断开连接

四、完整代码示例

4.1 服务器端实现

界面设计要点
  • 端口输入框:设置监听端口
  • 启动按钮:开始监听
  • 通信记录框:显示通信历史
  • 消息输入框:输入要发送的消息
  • 发送按钮:发送消息到客户端
  • 状态标签:显示服务器状态
核心代码实现
// 创建服务器对象
m_server = new QTcpServer(this);
// 监听新连接信号
connect(m_server, &QTcpServer::newConnection, this, [=]() {
// 获取客户端连接
m_tcp = m_server->nextPendingConnection();
record->append("成功和客户端建立了新的连接...");
m_status->setText("连接状态:√");
m_status->setStyleSheet("background-color:green");
// 监听客户端数据
connect(m_tcp, &QTcpSocket::readyRead, this, [=]() {
QString recvMsg = m_tcp->readAll();
record->append("客户端Say: " + recvMsg);
});
// 处理客户端断开
connect(m_tcp, &QTcpSocket::disconnected, this, [=]() {
record->append("客户端已经断开了连接...");
m_tcp->deleteLater();  // 安全删除对象
m_status->setText("连接状态:×");
m_status->setStyleSheet("background-color:red");
});
});
// 启动监听
void MainWindow::on_startServer_clicked() {
unsigned short port = m_port->text().toInt();
m_server->listen(QHostAddress::Any, port);
record->append("=========== 服务器已启动 ===========");
startServer->setEnabled(false);  // 禁用启动按钮
}
// 发送消息
void MainWindow::on_sendMsg_clicked() {
QString msg = msgInput->toPlainText();
if (m_tcp && m_tcp->state() == QAbstractSocket::ConnectedState) {
m_tcp->write(msg.toUtf8());
record->append("服务器Say: " + msg);
msgInput->clear();
}
}

4.2 客户端实现

界面设计要点
  • 服务器地址输入框:输入服务器IP
  • 端口输入框:输入服务器端口
  • 连接/断开按钮:控制连接状态
  • 通信记录框:显示通信历史
  • 消息输入框:输入要发送的消息
  • 发送按钮:发送消息到服务器
  • 状态标签:显示连接状态
核心代码实现
// 创建客户端套接字
m_tcp = new QTcpSocket(this);
// 监听数据接收
connect(m_tcp, &QTcpSocket::readyRead, [=]() {
QByteArray recvMsg = m_tcp->readAll();
record->append("服务器Say: " + recvMsg);
});
// 处理连接成功
connect(m_tcp, &QTcpSocket::connected, this, [=]() {
record->append("=========== 连接服务器成功 ===========");
m_status->setText("连接状态:√");
m_status->setStyleSheet("background-color:green");
connectServer->setEnabled(false);
disconnectBtn->setEnabled(true);
});
// 处理连接断开
connect(m_tcp, &QTcpSocket::disconnected, this, [=]() {
record->append("服务器已经断开了连接...");
m_status->setText("连接状态:×");
m_status->setStyleSheet("background-color:red");
connectServer->setEnabled(true);
disconnectBtn->setEnabled(false);
});
// 连接服务器
void MainWindow::on_connectServer_clicked() {
QString ip = m_ip->text();
unsigned short port = m_port->text().toInt();
m_tcp->connectToHost(QHostAddress(ip), port);
}
// 发送消息
void MainWindow::on_sendMsg_clicked() {
QString msg = msgInput->toPlainText();
if (m_tcp->state() == QAbstractSocket::ConnectedState) {
m_tcp->write(msg.toUtf8());
record->append("客户端Say: " + msg);
msgInput->clear();
}
}
// 断开连接
void MainWindow::on_disconnect_clicked() {
m_tcp->close();
}

五、关键技术与注意事项

5.1 数据编码与处理

  • 文本数据:使用QStringtoUtf8()进行编码转换
  • 二进制数据:使用QByteArray直接处理
  • 数据分帧:TCP是流式协议,需要应用层处理消息边界
    • 固定长度法:每条消息固定长度
    • 分隔符法:使用特定分隔符区分消息
    • 长度前缀法:在消息前添加长度信息

5.2 内存管理与资源释放

// 正确释放方式
clientSocket->deleteLater();  // 安全删除,由事件循环处理
// 避免野指针
connect(clientSocket, &QTcpSocket::disconnected,
clientSocket, &QTcpSocket::deleteLater);
// 服务器关闭时清理所有连接
void Server::closeAllConnections() {
for (QTcpSocket *socket : connections) {
socket->disconnectFromHost();
socket->deleteLater();
}
connections.clear();
}

5.3 错误处理机制

// 连接错误处理
connect(m_tcp, &QTcpSocket::errorOccurred, [](QAbstractSocket::SocketError error){
qDebug() << "套接字错误:" << error;
switch(error) {
case QAbstractSocket::ConnectionRefusedError:
qDebug() << "连接被拒绝";
break;
case QAbstractSocket::RemoteHostClosedError:
qDebug() << "远程主机关闭";
break;
// ... 其他错误处理
}
});
// 操作错误检查
qint64 bytesWritten = socket->write(data);
if (bytesWritten == -1) {
qDebug() << "发送失败:" << socket->errorString();
  // 重试或处理逻辑
  }

5.4 并发连接处理

// 多客户端连接管理
QList<QTcpSocket*> clientSockets;
  connect(m_server, &QTcpServer::newConnection, [=]() {
  QTcpSocket *clientSocket = m_server->nextPendingConnection();
  clientSockets.append(clientSocket);
  // 为每个客户端单独处理
  connect(clientSocket, &QTcpSocket::readyRead, [=]() {
  // 处理特定客户端的数据
  });
  // 客户端断开时清理
  connect(clientSocket, &QTcpSocket::disconnected, [=]() {
  clientSockets.removeOne(clientSocket);
  clientSocket->deleteLater();
  });
  });

六、高级特性与最佳实践

6.1 心跳机制实现

// 心跳定时器
QTimer *heartbeatTimer = new QTimer(this);
connect(heartbeatTimer, &QTimer::timeout, [=]() {
if (m_tcp->state() == QAbstractSocket::ConnectedState) {
m_tcp->write("HEARTBEAT");
// 检查上次心跳回复时间
if (lastHeartbeat.elapsed() > 30000) { // 30秒无回复
m_tcp->abort();  // 强制断开
}
}
});
heartbeatTimer->start(5000);  // 每5秒发送一次心跳

6.2 数据序列化

// 自定义协议结构
struct Message {
int type;           // 消息类型
int length;         // 数据长度
QByteArray data;    // 实际数据
QByteArray serialize() const {
QByteArray buffer;
QDataStream stream(&buffer, QIODevice::WriteOnly);
stream << type << length << data;
return buffer;
}
static Message deserialize(const QByteArray &buffer) {
Message msg;
QDataStream stream(buffer);
stream >> msg.type >> msg.length >> msg.data;
return msg;
}
};

6.3 性能优化建议

  1. 缓冲区管理:合理设置缓冲区大小
  2. 批量发送:合并小数据包,减少系统调用
  3. 异步处理:使用信号槽避免阻塞主线程
  4. 连接池:频繁连接时使用连接池复用
  5. 数据压缩:传输大量数据时考虑压缩

6.4 安全性考虑

  • 数据验证:验证接收数据的合法性
  • 访问控制:实现身份验证机制
  • 加密传输:敏感数据使用SSL/TLS加密
  • 限流控制:防止客户端过度消耗资源
  • 日志审计:记录重要操作和异常

七、调试与测试

7.1 常见问题排查

  1. 连接失败

    • 检查防火墙设置
    • 验证IP地址和端口
    • 确认服务器是否正在监听
  2. 数据丢失

    • 检查缓冲区大小
    • 验证数据分帧逻辑
    • 确认网络稳定性
  3. 内存泄漏

    • 使用Qt Creator内存分析工具
    • 检查deleteLater()调用
    • 验证父子对象关系

7.2 调试技巧

// 启用详细日志
qSetMessagePattern("[%{time yyyy-MM-dd hh:mm:ss.zzz}] "
"[%{if-debug}DEBUG%{endif}%{if-info}INFO%{endif}"
"%{if-warning}WARN%{endif}%{if-critical}ERROR%{endif}"
"%{if-fatal}FATAL%{endif}] %{file}:%{line} - %{message}");
// 网络状态监控
qDebug() << "Socket state:" << m_tcp->state();
  qDebug() << "Bytes available:" << m_tcp->bytesAvailable();
    qDebug() << "Peer address:" << m_tcp->peerAddress().toString();
      qDebug() << "Peer port:" << m_tcp->peerPort();

八、聊天室项目完整代码示例

注意:此代码只实现了单个客户端连接

8.1 服务器端实现

服务器端的窗口界面如下图所示:

服务器界面

头文件:mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
  #include <QTcpServer>
    #include <QTcpSocket>
      #include <QVBoxLayout>
        #include <QHBoxLayout>
          #include <QPushButton>
            #include <QLineEdit>
              #include <QTextEdit>
                #include <QLabel>
                  namespace Ui {
                  class MainWindow;
                  }
                  class MainWindow : public QMainWindow
                  {
                  Q_OBJECT
                  public:
                  explicit MainWindow(QWidget *parent = 0);
                  ~MainWindow();
                  private slots:
                  void on_startServer_clicked();
                  void on_sendMsg_clicked();
                  private:
                  Ui::MainWindow *ui;
                  QTcpServer* m_server;
                  QTcpSocket* m_tcp;
                  QLabel *plabel, *m_status;
                  QLineEdit *m_port;
                  QTextEdit *msg, *record;
                  QPushButton *startServer, *sendMsg;
                  };
                  #endif // MAINWINDOW_H
源文件:mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
centralWidget->setMinimumSize(500, 650);
// 整体垂直布局
QVBoxLayout *vlayout = new QVBoxLayout(centralWidget);
// 第一行:端口选择和服务器启动按钮
QHBoxLayout *playout = new QHBoxLayout(centralWidget);
vlayout->addLayout(playout);
plabel = new QLabel("端口:", this);
m_port = new QLineEdit(centralWidget);
m_port->setText("8888");  // 设置默认端口
m_port->setFixedWidth(100);
playout->addWidget(plabel);
playout->addWidget(m_port);
playout->addStretch();  // 加弹簧
startServer = new QPushButton("启动服务器", this);
startServer->setFixedWidth(100);
playout->addWidget(startServer);
// 通信记录对话框
QVBoxLayout *recordLayout = new QVBoxLayout;
vlayout->addLayout(recordLayout);
QLabel *recordLabel = new QLabel("通信记录:", centralWidget);
recordLabel->setMaximumWidth(150);
record = new QTextEdit(centralWidget);
record->resize(200, 100);
recordLayout->addWidget(recordLabel);
recordLayout->addWidget(record);
// 发送数据对话框
QVBoxLayout *msgLayout = new QVBoxLayout;
vlayout->addLayout(msgLayout);
QLabel *msgLabel = new QLabel("发送数据:", centralWidget);
msgLabel->setMaximumWidth(150);
msg = new QTextEdit(centralWidget);
msg->resize(200, 100);
msgLayout->addWidget(msgLabel);
msgLayout->addWidget(msg);
sendMsg = new QPushButton("广播消息", centralWidget);
msgLayout->addWidget(sendMsg);
// 服务器连接状态标签
m_status = new QLabel("服务器状态", centralWidget);
m_status->setStyleSheet("background-color:grey");
m_status->setMaximumWidth(150);
vlayout->addWidget(m_status);
// ============================ 服务器代码编写 ============================
setWindowTitle("TCP - 服务器");
// 创建 QTcpServer 对象
m_server = new QTcpServer(this);
// 检测是否有新的客户端连接
connect(m_server, &QTcpServer::newConnection, this, [=]() {
// 当有新的客户端连接时,会触发newConnection信号
m_tcp = m_server->nextPendingConnection();
// 通过nextPendingConnection()获取与客户端连接的QTcpSocket对象
record->append("成功和客户端建立了新的连接...");
m_status->setText("连接状态:√");
m_status->setStyleSheet("background-color:green");
// 检测是否有客户端数据
connect(m_tcp, &QTcpSocket::readyRead, this, [=]() {
// 当客户端有数据发送过来,触发readyRead信号
QString recvMsg = m_tcp->readAll();
record->append("客户端Say: " + recvMsg);
});
// 客户端断开了连接
connect(m_tcp, &QTcpSocket::disconnected, this, [=]() {
// 当客户端断开连接时,触发disconnected信号
record->append("客户端已经断开了连接...");
m_tcp->deleteLater();
// 将QTcpSocket对象标记为延迟删除,由Qt事件循环在适当时候安全删除
m_status->setText("连接状态:×");
m_status->setStyleSheet("background-color:red");
});
});
// 连接按钮信号和槽
connect(startServer, &QPushButton::clicked, this, &MainWindow::on_startServer_clicked);
connect(sendMsg, &QPushButton::clicked, this, &MainWindow::on_sendMsg_clicked);
}
MainWindow::~MainWindow()
{
delete ui;
}
// 启动服务器端的服务按钮
void MainWindow::on_startServer_clicked()
{
record->append("=========== 德玛西亚聊天室服务器已启动 ===========");
m_status->setText("连接状态:×");
m_status->setStyleSheet("background-color:red");
unsigned short port = m_port->text().toInt();
// 设置服务器监听
m_server->listen(QHostAddress::Any, port);
startServer->setEnabled(false);
}
// 点击发送数据按钮
void MainWindow::on_sendMsg_clicked()
{
QString m = msg->toPlainText();
m_tcp->write(m.toUtf8());
record->append("服务器Say: " + m);
msg->clear();
}

8.2 客户端实现

客户端的窗口界面如下图所示:

客户端界面

头文件:mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
  #include <QTcpServer>
    #include <QTcpSocket>
      #include <QVBoxLayout>
        #include <QHBoxLayout>
          #include <QPushButton>
            #include <QLineEdit>
              #include <QTextEdit>
                #include <QLabel>
                  namespace Ui {
                  class MainWindow;
                  }
                  class MainWindow : public QMainWindow
                  {
                  Q_OBJECT
                  public:
                  explicit MainWindow(QWidget *parent = 0);
                  ~MainWindow();
                  private slots:
                  void on_connectServer_clicked();
                  void on_sendMsg_clicked();
                  void on_disconnect_clicked();
                  private:
                  Ui::MainWindow *ui;
                  QTcpSocket* m_tcp;
                  QLabel *plabel, *slabel, *m_status;
                  QLineEdit *m_port, *m_ip;
                  QTextEdit *msg, *record;
                  QPushButton *connectServer, *disconnect, *sendMsg;
                  };
                  #endif // MAINWINDOW_H
源文件:mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
  MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
  {
  ui->setupUi(this);
  setWindowTitle("TCP - 客户端");
  QWidget *centralWidget = new QWidget(this);
  setCentralWidget(centralWidget);
  centralWidget->setMinimumSize(500, 650);
  // 整体垂直布局
  QVBoxLayout *vlayout = new QVBoxLayout(centralWidget);
  // 第一行:端口选择和服务器连接按钮
  QHBoxLayout *playout = new QHBoxLayout(centralWidget);
  vlayout->addLayout(playout);
  plabel = new QLabel("服务器端口:", this);
  m_port = new QLineEdit(centralWidget);
  m_port->setText("8888");  // 设置默认端口
  m_port->setFixedWidth(100);
  playout->addWidget(plabel);
  playout->addWidget(m_port);
  playout->addStretch();  // 加弹簧
  connectServer = new QPushButton("连接服务器", this);
  connectServer->setFixedWidth(100);
  playout->addWidget(connectServer);
  // 第二行:地址选择和服务器断开连接按钮
  QHBoxLayout *slayout = new QHBoxLayout(centralWidget);
  vlayout->addLayout(slayout);
  slabel = new QLabel("服务器地址:", this);
  m_ip = new QLineEdit(centralWidget);
  m_ip->setText("127.0.0.1"); // 设置默认地址
  m_ip->setFixedWidth(100);
  slayout->addWidget(slabel);
  slayout->addWidget(m_ip);
  slayout->addStretch();
  disconnect = new QPushButton("断开连接", this);
  disconnect->setFixedWidth(100);
  slayout->addWidget(disconnect);
  // 通信记录对话框
  QVBoxLayout *recordLayout = new QVBoxLayout;
  vlayout->addLayout(recordLayout);
  QLabel *recordLabel = new QLabel("通信记录:", centralWidget);
  recordLabel->setMaximumWidth(150);
  record = new QTextEdit(centralWidget);
  record->resize(200, 100);
  recordLayout->addWidget(recordLabel);
  recordLayout->addWidget(record);
  // 发送数据对话框
  QVBoxLayout *msgLayout = new QVBoxLayout;
  vlayout->addLayout(msgLayout);
  QLabel *msgLabel = new QLabel("发送数据:", centralWidget);
  msgLabel->setMaximumWidth(150);
  msg = new QTextEdit(centralWidget);
  msg->resize(200, 100);
  msgLayout->addWidget(msgLabel);
  msgLayout->addWidget(msg);
  sendMsg = new QPushButton("发送消息", centralWidget);
  vlayout->addWidget(sendMsg);
  // 服务器连接状态标签
  m_status = new QLabel("服务器状态:×", centralWidget);
  m_status->setStyleSheet("background-color:red");
  m_status->setMaximumWidth(150);
  vlayout->addWidget(m_status);
  // ============================ 客户端代码编写 ============================
  // 创建通信的套接字对象
  m_tcp = new QTcpSocket(this);
  // 检测服务器是否回复了数据
  connect(m_tcp, &QTcpSocket::readyRead, [=]() {
  // 接收服务器发送的数据
  QByteArray recvMsg = m_tcp->readAll();
  record->append("服务器Say: " + recvMsg);
  });
  // 检测是否和服务器是否连接成功了
  connect(m_tcp, &QTcpSocket::connected, this, [=]() {
  record->append("=========== 欢迎来到德玛西亚聊天室!!! ===========");
  m_status->setText("连接状态:√");
  m_status->setStyleSheet("background-color:green");
  // m_status->setPixmap(QPixmap("1.png").scaled(20, 20));
  });
  // 检测服务器是否和客户端断开了连接
  connect(m_tcp, &QTcpSocket::disconnected, this, [=]() {
  record->append("服务器已经断开了连接, ...");
  m_status->setText("连接状态:×");
  m_status->setStyleSheet("background-color:red");
  connectServer->setEnabled(true);
  disconnect->setEnabled(false);
  });
  // 连接按钮信号和槽
  connect(connectServer, &QPushButton::clicked, this, &MainWindow::on_connectServer_clicked);
  connect(sendMsg, &QPushButton::clicked, this, &MainWindow::on_sendMsg_clicked);
  connect(disconnect, &QPushButton::clicked, this, &MainWindow::on_disconnect_clicked);
  }
  MainWindow::~MainWindow()
  {
  delete ui;
  }
  // 连接服务器按钮按下之后的处理动作
  void MainWindow::on_connectServer_clicked()
  {
  QString ip = m_ip->text();
  unsigned short port = m_port->text().toInt();
  // 连接服务器
  m_tcp->connectToHost(QHostAddress(ip), port);
  connectServer->setEnabled(false);
  disconnect->setEnabled(true);
  }
  // 发送数据按钮按下之后的处理动作
  void MainWindow::on_sendMsg_clicked()
  {
  QString sendMsgText = msg->toPlainText();
  m_tcp->write(sendMsgText.toUtf8());
  record->append("客户端Say: " + sendMsgText);
  msg->clear();
  }
  // 断开连接按钮被按下之后的处理动作
  void MainWindow::on_disconnect_clicked()
  {
  m_tcp->close();
  connectServer->setEnabled(true);
  disconnect->setEnabled(false);
  }

posted @ 2026-01-20 17:08  yangykaifa  阅读(0)  评论(0)    收藏  举报