【QT】TCP

目录

核心API

示例:服务器和客户端信息互发

服务器代码实现

第一步:创建QTcpServer对象的实例

第二步:绑定信号槽,处理新的连接

第三步:绑定并监听端口号

客户端代码实现

第一步:创建socket对象的实例

第二步:和服务器建立连接

第三步:连接信号槽,处理响应 

第四步:等待连接结果,确认是否连接成功 

最终效果


UDP 无连接,不可靠传输,面向数据包,全双工

TCP 有连接,可靠传输,面向字节流,半双工

核心API

核心类是两个: QTcpServer QTcpSocket

QTcpServer ⽤于监听端⼝, 和获取客户端连接

名称
类型
说明
对标原⽣ API
listen(const QHostAddress&, quint16 port)
⽅法
绑定指定的地址和端⼝号, 并开始监听
bind 和 listen
nextPendingConnection()
⽅法
从系统中获取到⼀个已经建⽴好的 tcp 连接.
返回⼀个 QTcpSocket , 表⽰这个
客⼾端的连接.
通过这个 socket 对象完成和客⼾端 之间的通信
accept
newConnection
信号
有新的客⼾端建⽴连接好之后触发.
⽆ (但是类似于 IO 多路复⽤
中的通知机制)
QTcpSocket 用户客⼾端和服务器之间的数据交互
名称类型说明对标原⽣ API
readAll()
⽅法
读取当前接收缓冲区中的所有数据.
返回 QByteArray 对象.
read
write(const QByteArray& )
⽅法
把数据写⼊ socket 中.
write
deleteLater
⽅法
暂时把 socket 对象标记为⽆效. Qt
会在下个事件循环中析构释放该对
象.
⽆ (但是类似于 "半⾃动化的 垃圾回收")
readyRead
信号
有数据到达并准备就绪时触发
⽆ (但是类似于 IO 多路复⽤
中的通知机制)
disconnected
信号
连接断开时触发
⽆ (但是类似于 IO 多路复⽤
中的通知机制)

示例:服务器和客户端信息互发

服务器代码实现

首先区分QTcpServer 和 QTcpSocket,我们需要先使用QTcpServer来监听端⼝, 和获取客户端连接。

第一步:创建QTcpServer对象的实例

tcpServer = new QTcpServer(this代码);

第二步:绑定信号槽,处理新的连接

connect(tcpServer,&QTcpServer::newConnection,this,&Widget::processConnection);

processConnection方法 

void Widget::processConnection()

{

    //1.通过tcpserver拿到一个socket对象,通过这个对象来和客户端进行通信

    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();

    QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端上线了!";

    ui->listWidget->addItem(log);

    //2.通过信号槽,来处理客户端发来请求的情况

    connect(clientSocket,&QTcpSocket::readyRead,this,[=](){

       // a) 读取请求数据,此处readAll返回的是QByteArray,通过赋值转成 QString

       QString request = clientSocket->readAll();

       // b) 根据请求处理响应

       const QString& response = process(request);

       // c) 把响应写回到客户端

       clientSocket->write(response.toUtf8());

       // d) 把上述信息记录到日志中

       QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "]" + "req:" + request + ",resp:" + response;

    });

       ui->listWidget->addItem(log);

    //3. 通过信号槽,来处理客户端断开连接的情况

    connect(clientSocket,&QTcpSocket::disconnected,this,[=](){

        //a) 把断开连接的信息通过日志显示出来

       QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端下线了!";

       ui->listWidget->addItem(log);

       //b) 手动释放clientSocket

       clientSocket->deleteLater();

    });

}

注意: 

  • 在Linux网络编程中,需要搞一个循环,循环的读取请求,循环的处理,在Qt中基于信号槽就不必循环了。每次客户端发来请求,都能触发readyRead信号。
  • 因为QTcpSocket是每个客户端都有一个这样的对象,存在n个,所以必须在客户端断开连接后手动释放,而QTcpServer和QUdpSocket只有一份
  • clientSocket->deleteLater();这个操作,不是立即销毁clientSocket,而是告诉Qt,下一轮事件循环时,再进行销毁操作。

第三步:绑定并监听端口号

    bool ret = tcpServer->listen(QHostAddress::Any,9090);

    if(!ret)

    {

        QMessageBox::critical(this,"服务器启动失败!",tcpServer->errorString());

        exit(1);

    }

完整代码:

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void processConnection();QString process(const QString request);
private:Ui::Widget *ui;QTcpServer* tcpServer;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QTcpSocket>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//修改窗口标题this->setWindowTitle("服务器");//2.创建QTcpServer的实例tcpServer = new QTcpServer(this);//3.通过信号槽,指定如何处理连接connect(tcpServer,&QTcpServer::newConnection,this,&Widget::processConnection);//4.绑定并监听端口号bool ret = tcpServer->listen(QHostAddress::Any,9090);if(!ret){QMessageBox::critical(this,"服务器启动失败!",tcpServer->errorString());exit(1);}
}Widget::~Widget()
{delete ui;
}void Widget::processConnection()
{//1.通过tcpserver拿到一个socket对象,通过这个对象来和客户端进行通信QTcpSocket* clientSocket = tcpServer->nextPendingConnection();QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端上线了!";ui->listWidget->addItem(log);//2.通过信号槽,来处理客户端发来请求的情况connect(clientSocket,&QTcpSocket::readyRead,this,[=](){// a) 读取请求数据,此处readAll返回的是QByteArray,通过赋值转成 QStringQString request = clientSocket->readAll();// b) 根据请求处理响应const QString& response = process(request);// c) 把响应写回到客户端clientSocket->write(response.toUtf8());// d) 把上述信息记录到日志中QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "]" + "req:" + request + ",resp:" + response;ui->listWidget->addItem(log);});//3. 通过信号槽,来处理客户端断开连接的情况connect(clientSocket,&QTcpSocket::disconnected,this,[=](){//a) 把断开连接的信息通过日志显示出来QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端下线了!";ui->listWidget->addItem(log);//b) 手动释放clientSocketclientSocket->deleteLater();});
}QString Widget::process(const QString request)
{return request;
}

客户端代码实现

客户端不需要跟服务器一样监听端口,因此只需要创建socket即可

第一步:创建socket对象的实例

 tcpSocket = new QTcpSocket(this);

第二步:和服务器建立连接

 这个函数不会阻塞等待三次握手完成的(非阻塞函数)

tcpSocket->connectToHost("127.0.0.1",9090);

第三步:连接信号槽,处理响应 

 connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){

       QString response = tcpSocket->readAll();

        ui->listWidget->addItem("服务器说:"+response);

    });

第四步:等待连接结果,确认是否连接成功 

    bool ret = tcpSocket->waitForConnected();

    if(!ret){

        QMessageBox::critical(this,"连接服务器",tcpSocket->errorString());

    }

完整代码: 

 widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();private:Ui::Widget *ui;QTcpSocket* tcpSocket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//1.设置窗口标题this->setWindowTitle("客户端");//2.创建socket对象的实例tcpSocket = new QTcpSocket(this);//3.和服务器建立连接  这个函数不会阻塞等待三次握手完成的(非阻塞函数)tcpSocket->connectToHost("127.0.0.1",9090);//4. 连接信号槽,处理响应connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){QString response = tcpSocket->readAll();ui->listWidget->addItem("服务器说:"+response);});//5.等待连接建立的结果,确认是否连接成功bool ret = tcpSocket->waitForConnected();if(!ret){QMessageBox::critical(this,"连接服务器",tcpSocket->errorString());}
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//1.获取输入的内容const QString& text = ui->lineEdit->text();//2.发送数据给服务器tcpSocket->write(text.toUtf8());//3.把发送的信息显示到界面上ui->listWidget->addItem("客户端说:" + text);//4.清空输入框的内容ui->lineEdit->setText("");}

最终效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/49624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

financial是“财务”吗-《分析模式》漫谈14

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的Preface&#xff08;前言&#xff09;有这么一句&#xff1a; David Creager, Steve Shepherd, and their team at Citibank worked with me in developing t…

鱼哥好书分享活动第27期:看完这篇《云原生安全》了解云原生环境安全攻防实战技巧!

鱼哥好书分享活动第27期&#xff1a;看完这篇《云原生安全》了解云原生安全攻防实战技巧&#xff01; 主要内容&#xff1a;读者对象&#xff1a;本书目录&#xff1a;了解更多&#xff1a;赠书抽奖规则: 当前全球数字化的发展逐步进入深水区&#xff0c;云计算模式已经广泛应用…

免费【2024】springboot 超市在线销售系统的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

【MATLAB源码-第238期】基于simulink的三输出单端反激flyback仿真,通过PWM和PID控制能够得到稳定电压。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 概述 反激变换器是一种广泛应用于电源管理的拓扑结构&#xff0c;特别是在需要隔离输入和输出的应用中。它的工作原理是利用变压器的储能和释放能量来实现电压转换和隔离。该图展示了一个通过脉宽调制&#xff08;PWM&#…

7.24 补题

C 小w和大W的决斗 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 小w和大W为了比出谁更聪明。决定进行一场游戏。游戏内容如下: 两人轮流操作&#xff0c;小w先进行操作&#xff0c;每次操作可以选择下列两个其一: 选择数组中的一…

深度解析Linux-C——结构体(初始化,结构体数组,结构体大小,位段操作,联合体,内存对齐,C的预处理,宏和带参宏,条件编译)

目录 结构体的三种初始化 结构体的两种引用 结构体数组 结构体大小 结构体实现位段操作 联合体 内存对齐 C的预处理 带参宏 条件编译 结构体的三种初始化 定义如下结构体 struct student {char name[100]; int age; float height; } ; 1、定义变量时初始化 s…

tof系统标定流程步骤详解

1、tof标定概述 系统校准是一个减少ToF系统中系统误差影响的过程,如图1.1所示。本文件旨在介绍校准方法、设备和软件 1.1 系统误差 1.1.1 周期误差 谐波失真导致的相位(距离)相关误差。 1.1.2 固定相位模式噪声 由于解调信号的时延取决于可见像素位置以及VCSEL和传感器…

【Golang 面试基础题】每日 5 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

【机器学习】解开反向传播算法的奥秘

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 解开反向传播算法的奥秘反向传播算法的概述反向传播算法的数学推导1. 前向传播2…

Linux进程——程序地址空间详解

文章目录 程序地址空间地址空间与物理内存什么是程序地址空间管理程序地址空间虚拟地址与物理地址的映射页表的结构及其作用程序地址空间的作用 程序地址空间 我们之前学习内存的时候&#xff0c;有说内存的分布大概是这样的 其中堆由下而上&#xff0c;栈由上而下 除此之外&…

LeetCode:删除排序链表中的重复元素(C语言)

1、问题概述&#xff1a;给定一个已排序链表的头&#xff0c;删除重复元素&#xff0c;返回已排序的链表 2、示例 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] 3…

2024年国际高校数学建模大赛(IMMCHE)问题A:金字塔石的运输成品文章分享(仅供学习)

2024 International Mathematics Molding Contest for Higher Education Problem A: Transportation of Pyramid Stones&#xff08;2024年国际高校数学建模大赛&#xff08;IMMCHE&#xff09;问题A&#xff1a;金字塔石的运输&#xff09; 古埃及金字塔石材运输优化模型研究…

2024最新Selenium面试题(附带答案),建议收藏备用

一.你在TestNG中使用了哪些注解&#xff1f; TestBeforeSuiteAfterSuiteBeforeTestAfterTestBeforeClassAfterClassBeforeMethodAfterMethod 二.如何从Excel中读取数据&#xff1f; FileInputStream fs new FileInputStream(“excel文件路径”); Workbook wb WorkbookFact…

探索智慧校园资产入库功能,构建高效校园资产管理体系

在智慧校园的资产管理框架下&#xff0c;资产入库功能作为资产生命周期管理的开端&#xff0c;扮演着至关重要的角色。这一功能确保了新购置或转入的资产能够迅速而准确地被记录在系统中&#xff0c;从而无缝融入日常的管理流程。当资产入库时&#xff0c;系统要求详细登记一系…

2024最新前端学习路线指南!

2024最新前端学习路线指南&#xff01; 如果你正在寻找一份全面的前端学习路线图&#xff0c;那么这份精心打造的学习大纲恰好符合您的需求。无论您是新手还是经验丰富的开发者&#xff0c;这份路线图都能够帮助您系统地掌握前端开发的关键知识点&#xff0c;并在实践中不断提…

<PLC><HMI><汇川>在汇川HMI画面中,如何为UI设置全局样式?

前言 汇川的HMI软件是使用了Qt来编写的,因此在汇川的HMI程序编写过程,是支持使用qt的样式来自定义部件样式的,即qss格式。 概述 汇川的软件本身提供三个系统的style样式,我们可以直接使用,但是,如果系统提供的样式不符合你的需求,那么你可以对其进行修改,或者自己新建…

修改linux服务器上的mariadb/mysql数据库的密码

文章目录 一、查看数据库的状态二、修改密码 可能我们在最初安装数据库时没有设置密码或者已经设置了但是又想修改另一个密码&#xff0c;可以这样操作来修改我们的密码。 以数据库 mariadb 为例。 一、查看数据库的状态 使用命令 systemctl is-active mariadb 查看当前数据库…

Github 2024-07-27开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-27统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量非开发语言项目2C++项目2C项目2TypeScript项目1JavaScript项目1Java项目1Python项目1C#项目1免费编程学习平台:freeCodeCamp.org 创建周期:33…

JMeter接口测试:测试中奖概率!

介绍 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试领域&#xff0c;可用于测试静态和动态资源&#xff0c;如静态文件、Java 小服务程序、CGI 脚本、J…

Redis 缓存

安装 安装 Redis 下载&#xff1a; Releases tporadowski/redis (github.com) winr ----services.msc-----将redis 设置为手动(只是学习&#xff0c;如果经常用可以设置为自动) 安装 redis-py 库 pip install redis-py Redis 和 StrictRedis redis-py 提供 Redis 和 Str…