Qt网络编程-简易版TcpServer入门Demo(2) 原创
Qt网络编程-简易版TcpServer入门Demo(2)🦏
更多精彩内容 |
---|
👉个人内容分类汇总 👈 |
简易版 |
---|
👉Qt网络编程-简易版TcpClient入门Demo(1)👈 |
👉Qt网络编程-简易版TcpServer入门Demo(2)👈 |
👉Qt网络编程-简易版UDP单播通信入门Demo(3)👈 |
👉Qt网络编程-简易版UDP单播通信入门Demo(4)👈 |
👉Qt网络编程-简易版UDP组播通信入门Demo(5)👈 |
进阶版 |
---|
👉Qt网络编程-TcpClient入门Demo(1)👈 |
👉Qt网络编程-TcpServer入门Demo(2)👈 |
1、概述🐅
使用QTcpServer实现TCP Server,十分简易的入门Demo |
第一,绝对不意气用事;
第二,绝对不放过任何一个注释;
第三,绝对保证代码的简洁明了。🤘
为了便于学习,在这个Demo里会尽可能简单的实现TCP服务端功能,尽可能少的引入其它功能,只保留了基本功能,所以可能会有一些bug。
实现功能:
- 监听1个Tcp客户端连接功能,多余的连接自动断开;
- 数据接收功能;
- 数据发送功能
2、TCP服务端流程图🐴
- TCP服务端除了监听连接部分外,其它的和TCP客户端基本一样。
3、 关键信号🐕
信号 | 说明 |
---|---|
newConnection | QTcpServer监听到新的客户端连接 |
disconnected | QTcpSocket断开连接后发出此信号 |
readyRead | QTcpSocket有可读数据时发出此信号 |
4、 关键函数 🐶
函数名 | 说明 |
---|---|
isListening | 判断是否正在监听连接 |
listen | 绑定服务器侦听地址和端口上的传入连接。如果端口为0,则会自动选择一个端口。(相当于bind + listen ) |
nextPendingConnection | 返回已连接的QTcpSocket,如果有已连接的QTcpSocket没调用这个函数返回,将在QTcpServer释放时会自动统一释放(所以存在一定的内存泄漏问题) |
close | 关闭服务器。 服务器将不再监听传入连接 |
5、主要代码🦍
-
注意:在
.pro
文件里添加QT += network
,否则编译失败。 -
.h文件
/****************************************************************************** * @文件名 simpletcpserver.h * @功能 简易的TCP服务端Demo,只保留接听TCP(1个)客户端连接/断开、 数据发送、接收功能 * * @开发者 mhf * @邮箱 1603291350@qq.com * @时间 2022/04/17 * @备注 *****************************************************************************/ #ifndef SIMPLETCPSERVER_H #define SIMPLETCPSERVER_H #include <QWidget> #include <QTcpServer> namespace Ui { class SimpleTcpServer; } class SimpleTcpServer : public QWidget { Q_OBJECT public: explicit SimpleTcpServer(QWidget *parent = nullptr); ~SimpleTcpServer(); private slots: void on_newConnection(); void on_disconnected(); void on_readyRead(); void on_but_connect_clicked(); void on_but_send_clicked(); private: Ui::SimpleTcpServer *ui; QTcpServer* m_server = nullptr; // TCP服务端对象 QTcpSocket* m_client = nullptr; // 连接成功的客户端 }; #endif // SIMPLETCPSERVER_H
-
.cpp文件
#include "simpletcpserver.h" #include "ui_simpletcpserver.h" #include <qtcpsocket.h> SimpleTcpServer::SimpleTcpServer(QWidget *parent) : QWidget(parent), ui(new Ui::SimpleTcpServer) { ui->setupUi(this); this->setWindowTitle("简易版本TCP 服务端Demo"); m_server = new QTcpServer(this); connect(m_server, &QTcpServer::newConnection, this, &SimpleTcpServer::on_newConnection); // 监听新的客户端连接 } SimpleTcpServer::~SimpleTcpServer() { delete ui; } void SimpleTcpServer::on_but_connect_clicked() { if(!m_server->isListening()) // 判断是否正在监听连接 { // 告诉服务器侦听地址和端口上的传入连接。如果端口为0,则会自动选择一个端口。 // 如果地址是QHostAddress::Any,服务器将监听所有网络接口。 bool ret = m_server->listen(QHostAddress::Any, ui->spin_localPort->value()); if(ret) { ui->but_connect->setText("停止"); } else { qDebug() << QString("tcpServer绑定监听IP、端口失败:%1 %2").arg(m_server->errorString()).arg(m_server->serverError()); } } else { m_client->abort(); m_server->close(); ui->but_connect->setText("开始监听"); } } /** * @brief 如果有新的TCP客户端发起连接,则会在这个函数中返回连接成功的QTcpSocket; * 这里只保留第一个连接成功的客户端,其它的自动断开连接 */ void SimpleTcpServer::on_newConnection() { QTcpSocket* tcpSocket = m_server->nextPendingConnection(); // 存在内存泄漏,最好使用时通过hasPendingConnections判断是否有未返回的连接 if(tcpSocket) { if(m_client) // 如果已经有连接的 客户端,则断开后面所有的连接 { tcpSocket->deleteLater(); return; } m_client = tcpSocket; connect(tcpSocket, &QTcpSocket::disconnected, this, &SimpleTcpServer::on_disconnected); // 断开连接 connect(tcpSocket, &QTcpSocket::readyRead, this, &SimpleTcpServer::on_readyRead); // 接收客户端发来的数据 } } /** * @brief 断开连接 */ void SimpleTcpServer::on_disconnected() { disconnect(m_client, &QTcpSocket::disconnected, this, &SimpleTcpServer::on_disconnected); // 断开绑定的信号槽 disconnect(m_client, &QTcpSocket::readyRead, this, &SimpleTcpServer::on_readyRead); //delete m_client; // 这里不能用delete,否则在vs里会报错 0x00007FFBF870A1CE (Qt5Networkd.dll)处(位于 QMNetwork.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。 QTcpSocket* tcpSocket = m_client; m_client = nullptr; // 先将m_client置空,因为deleteLater不会置空 tcpSocket->deleteLater(); // 移除已经断开连接的Client(注意这里不能使用delete,否则在vs中会报错),但这种方式不会置为 空 } /** * @brief 接收数据,这里和TCP Client是一样的 */ void SimpleTcpServer::on_readyRead() { QByteArray dataArr = m_client->readAll(); // 一次性读取缓存中所有数据 if(dataArr.count() <= 0) // 没有读取到数据 { return; } ui->text_recv->append(dataArr); // 显示读取到的数据 } /** * @brief 发送数据,这里和TCP Client是一样的 */ void SimpleTcpServer::on_but_send_clicked() { if(!m_client) return; // 判断是否为空,如果为空则未连接 if(m_client->state() != QAbstractSocket::ConnectedState) return; // 判断TCP是否已连接,如果没有连接则不发送数据 QString str = ui->text_send->toPlainText(); // 获取输入框的内容 qint64 len = m_client->write(str.toUtf8()); // 发送数据,toUtf8()是为了支持发送中文,但是如果接收端编码方式不同则中文可能显示乱码 if(len < 0) { qWarning() <<"发送失败!"; } }
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏