【Qt】TCP套接字通信学习文档
📚 一、概述
1.1 标准C++与Qt在网络编程上的区别
| 特性 | 标准C++ | Qt框架 |
|---|---|---|
| 套接字支持 | 无内置类,需使用操作系统C API | 提供QTcpServer、QTcpSocket等类 |
| 开发复杂度 | 较高,需要处理平台差异 | 较低,跨平台API统一 |
| 编程范式 | 面向过程/手动封装 | 面向对象,信号槽机制 |
| 内存管理 | 手动管理 | 父子对象机制自动管理 |
| 异步处理 | 需要多线程/select/poll等 | 信号槽机制简化异步处理 |
1.2 Qt网络编程优势 ✨
- 跨平台性:一次编写,多平台运行(Windows、Linux、macOS等)
- 信号槽机制:事件驱动,避免阻塞式编程
- 简化开发:封装底层细节,提供高级API
- 集成度高:与Qt GUI、数据库等模块无缝集成
- 内存安全:父子对象机制减少内存泄漏风险
🔧 二、核心类详解
2.1 QTcpServer - 服务器类
📋 主要功能
- 监听客户端连接请求
- 建立与客户端的连接
- 管理客户端连接队列
🛠️ 常用API函数
构造函数
cpp
QTcpServer::QTcpServer(QObject *parent = nullptr);
监听绑定
cpp
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表示自动分配可用端口
状态查询
cpp
bool QTcpServer::isListening() const; // 是否正在监听
QHostAddress QTcpServer::serverAddress() const; // 服务器绑定地址
quint16 QTcpServer::serverPort() const; // 服务器绑定端口
连接管理
cpp
QTcpSocket *QTcpServer::nextPendingConnection(); // 获取待处理的连接
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = nullptr);
🔔 重要信号
cpp
void newConnection(); // 有新客户端连接时触发
void acceptError(QAbstractSocket::SocketError socketError); // 接受连接出错时触发
2.2 QTcpSocket - 通信套接字类
📊 继承关系
QObject → QIODevice → QAbstractSocket → QTcpSocket
🛠️ 常用API函数
构造函数
cpp
QTcpSocket::QTcpSocket(QObject *parent = nullptr);
连接服务器
cpp
void connectToHost(const QString &hostName, quint16 port,
QIODevice::OpenMode openMode = QIODevice::ReadWrite);
void connectToHost(const QHostAddress &address, quint16 port,
QIODevice::OpenMode openMode = QIODevice::ReadWrite);
数据读写操作
cpp
// 读取数据
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); // 等待可读数据
连接状态
cpp
bool isOpen() const; // 套接字是否打开
bool isReadable() const; // 是否可读
bool isWritable() const; // 是否可写
void close(); // 关闭套接字
🔔 重要信号
cpp
void readyRead(); // 有数据可读时触发
void connected(); // 连接建立成功时触发
void disconnected(); // 连接断开时触发
void bytesWritten(qint64 bytes); // 数据写入完成时触发
void errorOccurred(QAbstractSocket::SocketError socketError); // 错误发生时触发
void stateChanged(QAbstractSocket::SocketState socketState); // 状态改变时触发
🔄 三、TCP通信流程
3.1 服务器端完整流程
📝 通信流程步骤
- 创建QTcpServer对象 - 实例化服务器对象
- 启动监听 - 调用
listen()方法绑定地址和端口 - 处理新连接 - 连接
newConnection信号,在槽函数中处理 - 获取通信套接字 - 使用
nextPendingConnection()获取客户端套接字 - 数据通信 - 通过客户端套接字进行读写操作
- 连接管理 - 处理连接断开和异常情况
📊 流程图示
创建QTcpServer listen绑定地址端口 连接newConnection信号 客户端连接触发信号 nextPendingConnection获取QTcpSocket 连接readyRead信号读取数据 使用write发送数据 处理disconnected信号清理资源
3.2 客户端完整流程
📝 通信流程步骤
- 创建QTcpSocket对象 - 实例化客户端套接字
- 连接服务器 - 调用
connectToHost()连接服务器 - 处理连接状态 - 连接
connected、disconnected信号 - 数据通信 - 连接
readyRead信号读取数据,使用write()发送数据 - 断开连接 - 调用
close()或处理服务器断开
📊 流程图示
创建QTcpSocket connectToHost连接服务器 connected信号确认连接 连接readyRead信号读取数据 使用write发送数据 处理disconnected信号 close断开连接
💻 四、完整代码示例
4.1 服务器端实现
🎨 界面设计要点
- 端口输入框:设置监听端口
- 启动按钮:开始监听
- 通信记录框:显示通信历史
- 消息输入框:输入要发送的消息
- 发送按钮:发送消息到客户端
- 状态标签:显示服务器状态
📝 核心代码实现
cpp
// 创建服务器对象
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
- 端口输入框:输入服务器端口
- 连接/断开按钮:控制连接状态
- 通信记录框:显示通信历史
- 消息输入框:输入要发送的消息
- 发送按钮:发送消息到服务器
- 状态标签:显示连接状态
📝 核心代码实现
cpp
// 创建客户端套接字
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 数据编码与处理
- 文本数据 :使用
QString和toUtf8()进行编码转换 - 二进制数据 :使用
QByteArray直接处理 - 数据分帧 :TCP是流式协议,需要应用层处理消息边界
- 固定长度法:每条消息固定长度
- 分隔符法:使用特定分隔符区分消息
- 长度前缀法:在消息前添加长度信息
5.2 内存管理与资源释放
cpp
// 正确释放方式
clientSocket->deleteLater(); // 安全删除,由事件循环处理
// 避免野指针
connect(clientSocket, &QTcpSocket::disconnected,
clientSocket, &QTcpSocket::deleteLater);
// 服务器关闭时清理所有连接
void Server::closeAllConnections() {
for (QTcpSocket *socket : connections) {
socket->disconnectFromHost();
socket->deleteLater();
}
connections.clear();
}
5.3 错误处理机制
cpp
// 连接错误处理
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 并发连接处理
cpp
// 多客户端连接管理
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 心跳机制实现
cpp
// 心跳定时器
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 数据序列化
cpp
// 自定义协议结构
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 性能优化建议
- 缓冲区管理:合理设置缓冲区大小
- 批量发送:合并小数据包,减少系统调用
- 异步处理:使用信号槽避免阻塞主线程
- 连接池:频繁连接时使用连接池复用
- 数据压缩:传输大量数据时考虑压缩
6.4 安全性考虑
- 数据验证:验证接收数据的合法性
- 访问控制:实现身份验证机制
- 加密传输:敏感数据使用SSL/TLS加密
- 限流控制:防止客户端过度消耗资源
- 日志审计:记录重要操作和异常
🔍 七、调试与测试
7.1 常见问题排查
-
连接失败
- 检查防火墙设置
- 验证IP地址和端口
- 确认服务器是否正在监听
-
数据丢失
- 检查缓冲区大小
- 验证数据分帧逻辑
- 确认网络稳定性
-
内存泄漏
- 使用Qt Creator内存分析工具
- 检查
deleteLater()调用 - 验证父子对象关系
7.2 调试技巧
cpp
// 启用详细日志
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
cpp
#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
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
cpp
#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
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);
}