qt triggered信号_Qt之网络编程UDP通信
点击上方“Qt学视觉”,选择“星标”公众号重磅干货,第一时间送达
想要学习的同学们还请认真阅读每篇文章,相信你一定会有所收获
UDP通信概述
UDP(UserDatagramProtocol,用户数据报协议)是轻量的、不可靠的、面向数据报(datagram)、无连接的协议,它可以用于对可靠性要求不高的场合与TCP通信不同,两个程序之间进行UDP通信无 需预先建立持久的socket连接,UDP每次发送数据报都需要指定目标地址和端口(如下图所示)。
QUdpSocket类用于实现UDP通信,它从QAbstractSocket类继承,因而与QTcpSocket共享 大部分的接口函数。主要区别是QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数 据报使用函数QUdpSocket::writeDatagram(),数据报的长度一般少于512字节,每个数据报包含发 送者和接收者的IP地址和端口等信息。
要进行UDP数据接收,要用QUdpSocket::bind()函数先绑定一个端口,用于接收传入的数据 报。当有数据报传入时会发射readyRead()信号,使用readDatagram()函数来读取接收到的数据报。UDP消息传送有单播、广播、组播三种模式
单播(unicast)模式:一个UDP客户端发出的数据报只发送到另一个指定地址和端口的 UDP客户端,是一对一的数据传输。
广播(broadcast)模式:一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以收到。QUdpSocket支持IPv4广播。广播经常用于实现网络发现的协议。要获取广播数据只需在数据报中指定接收端地址为QHostAddres::Broadcast, —般的广播 地址是 255.255.255.255。
组播(multicast)模式:也称为多播。UDP客户端加入到另一个组播IP地址指定的多播 组,成员向组播地址发送的数据报组内成员都可以接收到,类似于QQ群的功能. QUdpSocket::joinMulticastGroup()函数实现加入多播组的功能,加入多播组后,UDP数据 的收发与正常的UDP数据收发方法一样。
使用广播和多播模式,UDP可以实现一些比较灵活的通信功能,而TCP通信只有单播模式, 没有广播和多播模式。所以,UDP通信虽然不能保证数据传输的准确性,但是具有灵活性,一般 的即时通信软件都是基于UDP通信的。
QUdpSocket类从QAbstractSocket继承而来,但是又定义了较多新的功能函数用于实现UDP 特有的一些功能,如数据报读写和多播通信功能。QUdpSocket没有定义新的信号。QUdpSocket 的主要功能函数见表
bool bind(quint 16 port = 0)
为UDP通信绑定一个端口
qint64 writeDatagram(QByteArray &datagram, QHostAddress &host, quint 16 port)
向目标地址和端口的UDP客户端发送数据报,返回成功 发送的字节数
bool hasPendingDatagrams()
当至少有一个数据报需要读取时,返回true
qint64 pendingDatagramSize()
返回第一个待读取的数据报的大小
qint64 readDatagram(char *data, qint64 maxSize)
读取一个数据报,返回成功读取的数据报的字节数
bool joinMulticastGroup(QHostAddress &groupAddress)
加入一个多播组
bool leaveMulticastGroup(QHostAddress &groupAddress)
离开一个多播组
在单播、广播和多播模式下,UDP程序都是对等的,不像TCP通信那样分为客户端和服务器 端。多播和广播的实现方式基本相同,只是数据报的目标IP地址设置不同,多播模式需要加入多 播组,实现方式有较大差异。
例程如下
头文件
#pragma once#include #include "ui_QGuiUdpClient.h"#include #include class QGuiUdpClient : public QMainWindow{ Q_OBJECTpublic: QGuiUdpClient(QWidget *parent = Q_NULLPTR); ~QGuiUdpClient();private slots: //自定义槽函数 void onSocketStateChange(QAbstractSocket::SocketState socketState); void onSocketReadyRead();//读取socket传入的数据 void actStart_triggered(); void actStop_triggered(); void actHostInfo_triggered(); void actClear_triggered(); void btnSend_clicked(); void btnBroadcast_clicked();private: Ui::QGuiUdpClient ui;private: QLabel* m_pLabSocketState;//socket状态显示标签 QUdpSocket* m_pUdpSocket;// QString getLocalIP();//获取本机IP地址};
源文件
#include "QGuiUdpClient.h"#include #pragma execution_character_set("utf-8")QGuiUdpClient::QGuiUdpClient(QWidget *parent) : QMainWindow(parent){ ui.setupUi(this); m_pLabSocketState = new QLabel("Socket状态:");// m_pLabSocketState->setMinimumWidth(200); ui.statusBar->addWidget(m_pLabSocketState); QString localIP = getLocalIP();//本机IP this->setWindowTitle(this->windowTitle() + "----本机IP:" + localIP); ui.comboTargetIP->addItem(localIP); m_pUdpSocket = new QUdpSocket(this);//用于与连接的客户端通讯的QTcpSocket connect(m_pUdpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState))); onSocketStateChange(m_pUdpSocket->state()); connect(m_pUdpSocket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead())); connect(ui.actStart, SIGNAL(triggered()), this, SLOT(actStart_triggered())); connect(ui.actStop, SIGNAL(triggered()), this, SLOT(actStop_triggered())); connect(ui.actHostInfo, SIGNAL(triggered()), this, SLOT(actHostInfo_triggered())); connect(ui.actClear, SIGNAL(triggered()), this, SLOT(actClear_triggered())); connect(ui.btnSend, SIGNAL(clicked()), this, SLOT(btnSend_clicked())); connect(ui.btnBroadcast, SIGNAL(clicked()), this, SLOT(btnBroadcast_clicked()));}QGuiUdpClient::~QGuiUdpClient(){ m_pUdpSocket->abort(); delete m_pUdpSocket;}void QGuiUdpClient::onSocketStateChange(QAbstractSocket::SocketState socketState){ switch (socketState) { case QAbstractSocket::UnconnectedState: m_pLabSocketState->setText("scoket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: m_pLabSocketState->setText("scoket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: m_pLabSocketState->setText("scoket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: m_pLabSocketState->setText("scoket状态:ConnectedState"); break; case QAbstractSocket::BoundState: m_pLabSocketState->setText("scoket状态:BoundState"); break; case QAbstractSocket::ClosingState: m_pLabSocketState->setText("scoket状态:ClosingState"); break; case QAbstractSocket::ListeningState: m_pLabSocketState->setText("scoket状态:ListeningState"); break; }}void QGuiUdpClient::onSocketReadyRead(){ while (m_pUdpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(m_pUdpSocket->pendingDatagramSize()); QHostAddress peerAddr; quint16 peerPort; m_pUdpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort); QString str = datagram.data(); QString peer = "[From " + peerAddr.toString() + ":" + QString::number(peerPort) + "] "; ui.plainTextEdit->appendPlainText(peer + str); }}void QGuiUdpClient::actStart_triggered(){ quint16 port = ui.spinBindPort->value(); //本机UDP端口 if (m_pUdpSocket->bind(port))//绑定端口成功 { ui.plainTextEdit->appendPlainText("**已成功绑定"); ui.plainTextEdit->appendPlainText("**绑定端口:" + QString::number(m_pUdpSocket->localPort())); ui.actStart->setEnabled(false); ui.actStop->setEnabled(true); } else ui.plainTextEdit->appendPlainText("**绑定失败");}void QGuiUdpClient::actStop_triggered(){ m_pUdpSocket->abort(); //不能解除绑定 ui.actStart->setEnabled(true); ui.actStop->setEnabled(false); ui.plainTextEdit->appendPlainText("**已解除绑定");}void QGuiUdpClient::actHostInfo_triggered(){ QString hostName = QHostInfo::localHostName();//本地主机名 ui.plainTextEdit->appendPlainText("本机主机名:" + hostName + "\n"); QHostInfo hostInfo = QHostInfo::fromName(hostName); QList addList = hostInfo.addresses();// if (!addList.isEmpty()) { for (int i = 0; i < addList.count(); i++) { QHostAddress aHost = addList.at(i); if (QAbstractSocket::IPv4Protocol == aHost.protocol()) { QString IP = aHost.toString(); ui.plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString()); if (ui.comboTargetIP->findText(IP) < 0) ui.comboTargetIP->addItem(IP); } } }}void QGuiUdpClient::actClear_triggered(){ ui.plainTextEdit->clear();}void QGuiUdpClient::btnSend_clicked(){ QString targetIP = ui.comboTargetIP->currentText(); //目标IP QHostAddress targetAddr(targetIP); quint16 targetPort = ui.spinTargetPort->value();//目标port QString msg = ui.editMsg->text();//发送的消息内容 QByteArray str = msg.toUtf8(); m_pUdpSocket->writeDatagram(str, targetAddr, targetPort); //发出数据报 ui.plainTextEdit->appendPlainText("[out] " + msg); ui.editMsg->clear(); ui.editMsg->setFocus();}void QGuiUdpClient::btnBroadcast_clicked(){ quint16 targetPort = ui.spinTargetPort->value(); //目标端口 QString msg = ui.editMsg->text(); QByteArray str = msg.toUtf8(); m_pUdpSocket->writeDatagram(str, QHostAddress::Broadcast, targetPort); ui.plainTextEdit->appendPlainText("[broadcast] " + msg); ui.editMsg->clear(); ui.editMsg->setFocus();}QString QGuiUdpClient::getLocalIP(){ QString hostName = QHostInfo::localHostName();//本地主机名 QHostInfo hostInfo = QHostInfo::fromName(hostName); QString localIP = ""; QList addList = hostInfo.addresses();// if (!addList.isEmpty()) { for (int i = 0; i < addList.count(); i++) { QHostAddress aHost = addList.at(i); if (QAbstractSocket::IPv4Protocol == aHost.protocol()) { localIP = aHost.toString(); break; } } } return localIP;}
头文件
#pragma once#include #include "ui_QGuiUdpServer.h"#include #include class QGuiUdpServer : public QMainWindow{ Q_OBJECTpublic: QGuiUdpServer(QWidget *parent = Q_NULLPTR); ~QGuiUdpServer();private slots: //自定义槽函数 void onSocketStateChange(QAbstractSocket::SocketState socketState); void onSocketReadyRead();//读取socket传入的数据 void actStart_triggered(); void actStop_triggered(); void actHostInfo_triggered(); void actClear_triggered(); void btnSend_clicked(); void btnBroadcast_clicked();private: Ui::QGuiUdpServer ui;private: QLabel* m_pLabSocketState;//socket状态显示标签 QUdpSocket* m_pUdpSocket;// QString getLocalIP();//获取本机IP地址};
源文件
#include "QGuiUdpServer.h"#include #pragma execution_character_set("utf-8")QGuiUdpServer::QGuiUdpServer(QWidget *parent) : QMainWindow(parent){ ui.setupUi(this); m_pLabSocketState = new QLabel("Socket状态:");// m_pLabSocketState->setMinimumWidth(200); ui.statusBar->addWidget(m_pLabSocketState); QString localIP = getLocalIP();//本机IP this->setWindowTitle(this->windowTitle() + "----本机IP:" + localIP); ui.comboTargetIP->addItem(localIP); m_pUdpSocket = new QUdpSocket(this);//用于与连接的客户端通讯的QTcpSocket connect(m_pUdpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState))); onSocketStateChange(m_pUdpSocket->state()); connect(m_pUdpSocket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead())); connect(ui.actStart, SIGNAL(triggered()), this, SLOT(actStart_triggered())); connect(ui.actStop, SIGNAL(triggered()), this, SLOT(actStop_triggered())); connect(ui.actHostInfo, SIGNAL(triggered()), this, SLOT(actHostInfo_triggered())); connect(ui.actClear, SIGNAL(triggered()), this, SLOT(actClear_triggered())); connect(ui.btnSend, SIGNAL(clicked()), this, SLOT(btnSend_clicked())); connect(ui.btnBroadcast, SIGNAL(clicked()), this, SLOT(btnBroadcast_clicked()));}QGuiUdpServer::~QGuiUdpServer(){ m_pUdpSocket->abort(); delete m_pUdpSocket;}void QGuiUdpServer::onSocketStateChange(QAbstractSocket::SocketState socketState){ switch (socketState) { case QAbstractSocket::UnconnectedState: m_pLabSocketState->setText("scoket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: m_pLabSocketState->setText("scoket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: m_pLabSocketState->setText("scoket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: m_pLabSocketState->setText("scoket状态:ConnectedState"); break; case QAbstractSocket::BoundState: m_pLabSocketState->setText("scoket状态:BoundState"); break; case QAbstractSocket::ClosingState: m_pLabSocketState->setText("scoket状态:ClosingState"); break; case QAbstractSocket::ListeningState: m_pLabSocketState->setText("scoket状态:ListeningState"); break; }}void QGuiUdpServer::onSocketReadyRead(){ while (m_pUdpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(m_pUdpSocket->pendingDatagramSize()); QHostAddress peerAddr; quint16 peerPort; m_pUdpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort); QString str = datagram.data(); QString peer = "[From " + peerAddr.toString() + ":" + QString::number(peerPort) + "] "; ui.plainTextEdit->appendPlainText(peer + str); }}void QGuiUdpServer::actStart_triggered(){ quint16 port = ui.spinBindPort->value(); //本机UDP端口 if (m_pUdpSocket->bind(port))//绑定端口成功 { ui.plainTextEdit->appendPlainText("**已成功绑定"); ui.plainTextEdit->appendPlainText("**绑定端口:" + QString::number(m_pUdpSocket->localPort())); ui.actStart->setEnabled(false); ui.actStop->setEnabled(true); } else ui.plainTextEdit->appendPlainText("**绑定失败");}void QGuiUdpServer::actStop_triggered(){ m_pUdpSocket->abort(); //不能解除绑定 ui.actStart->setEnabled(true); ui.actStop->setEnabled(false); ui.plainTextEdit->appendPlainText("**已解除绑定");}void QGuiUdpServer::actHostInfo_triggered(){ QString hostName = QHostInfo::localHostName();//本地主机名 ui.plainTextEdit->appendPlainText("本机主机名:" + hostName + "\n"); QHostInfo hostInfo = QHostInfo::fromName(hostName); QList addList = hostInfo.addresses();// if (!addList.isEmpty()) { for (int i = 0; i < addList.count(); i++) { QHostAddress aHost = addList.at(i); if (QAbstractSocket::IPv4Protocol == aHost.protocol()) { QString IP = aHost.toString(); ui.plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString()); if (ui.comboTargetIP->findText(IP) < 0) ui.comboTargetIP->addItem(IP); } } }}void QGuiUdpServer::actClear_triggered(){ ui.plainTextEdit->clear();}void QGuiUdpServer::btnSend_clicked(){ QString targetIP = ui.comboTargetIP->currentText(); //目标IP QHostAddress targetAddr(targetIP); quint16 targetPort = ui.spinTargetPort->value();//目标port QString msg = ui.editMsg->text();//发送的消息内容 QByteArray str = msg.toUtf8(); m_pUdpSocket->writeDatagram(str, targetAddr, targetPort); //发出数据报 ui.plainTextEdit->appendPlainText("[out] " + msg); ui.editMsg->clear(); ui.editMsg->setFocus();}void QGuiUdpServer::btnBroadcast_clicked(){ quint16 targetPort = ui.spinTargetPort->value(); //目标端口 QString msg = ui.editMsg->text(); QByteArray str = msg.toUtf8(); m_pUdpSocket->writeDatagram(str, QHostAddress::Broadcast, targetPort); ui.plainTextEdit->appendPlainText("[broadcast] " + msg); ui.editMsg->clear(); ui.editMsg->setFocus();}QString QGuiUdpServer::getLocalIP(){ QString hostName = QHostInfo::localHostName();//本地主机名 QHostInfo hostInfo = QHostInfo::fromName(hostName); QString localIP = ""; QList addList = hostInfo.addresses();// if (!addList.isEmpty()) { for (int i = 0; i < addList.count(); i++) { QHostAddress aHost = addList.at(i); if (QAbstractSocket::IPv4Protocol == aHost.protocol()) { localIP = aHost.toString(); break; } } } return localIP;}
qt triggered信号_Qt之网络编程UDP通信相关推荐
- 网络编程 UDP通信的过程 TCP通信过程 多线程文件上传
网络概述 协议 在网络之间传出数据时需要按照指定的标准来传输,标准中规定了数据的格式.大小.传输的方式.传输速率.形成统一规范->按照规范开发的代码->协议(应用层.传输层.网络层.链路层 ...
- python网络编程——UDP通信附实例参考
简介 在网络通信编程中,用的最多的就是UDP和TCP通信了,原理这里就不分析了,网上介绍也很多,这里简单列举一下各自的优缺点和使用场景 通信方式 优点 缺点 适用场景 UDP 及时性好,快速 视网络情 ...
- qt tcp通信_Qt之网络编程TCP通信
点击上方"Qt学视觉",选择"星标"公众号重磅干货,第一时间送达 想要学习的同学们还请认真阅读每篇文章,相信你一定会有所收获 TCP通信概述 TCP(Trans ...
- [Java网络编程]UDP通信程序练习
代码如下: package UdpPracticePack;import java.io.BufferedReader; import java.io.IOException; import java ...
- 基于QT的【第一个项目】设计+所有组件配合使用+网络编程局域网通信+文件IO操作+登录界面和头像+多界面跳转+JSON数据解析+表情包制作
基于QT的第一个项目+所有组件配合使用+网络编程局域网通信+文件IO操作+登录界面和头像+多界面跳转+JSON数据解析+表情包制作 第一阶段 网络编程局域网TCP/IP聊天QT实现 main.c ma ...
- c++网络编程UDP
c++网络编程UDP 服务器端: #include<WinSock2.h> #include<iostream>#pragma comment(lib,"ws2_32 ...
- Java SE基础知识详解第[18]期—网络编程(通信)
写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...
- QT入门第七天 网络编程TCP/IP/UDP+Http和JSON解析+qt事件软键盘【CSDN最详细】
网络编程+Http和JSON解析+qt事件软键盘 第一章 QT中的网络编程 [1]涉及到的类 [2]tcp协议的流程 [2.1]服务器的流程 socket-->bind-->listen- ...
- Java网络编程UDP编程
一. 简单先介绍一下网络编程 1. 概念 : 通过网络IP连接起来,实现网络通信,数据传输的操作,就是网络编程 2. 实现 : 目前来说当前主要有两种实现的方法,TCP和UDP: 其中TCP需要划分客 ...
最新文章
- ASP——限制表单提交时间期限简单示例
- Python基础七(函数)
- Python数模笔记-PuLP库(2)线性规划进阶
- js用ajax和不同页面的php互相传值的方法
- configure: error: cannot guess build type; you must specify one解决方法
- c++小程序代码_# 微信小程序的原生框架和taro对比 ##
- opencv舌头监测模型+keras神经网络(LeNet)
- C语言--------学生管理系统(源代码)
- 最新win7/win10/XP系统下载_「装机系统」_百度云
- 怎样系统的学习计算机编程,如何学习电脑编程
- Java 8 Nashorn 教程
- 百度云开发clouda学习(一)
- 《贝叶斯统计》最大后验密度可信集(HPD)Python实现
- 微信小程序的wx:for和vue的v-for
- Discuz被挂马的处理经验,Dz为什么会被挂马
- SLCP验厂辅导,发布网关是SLCP系统中用于数据托管和共享的关键角色
- 云服务PaaS、SaaS、IaaS
- 纯js实现省市区三级联动
- codevs 2832 6个朋友 并查集 解题报告
- 分享一下我收藏很久的一些代替百度的搜索引擎网站
热门文章
- linux定时scp脚本,linux expect 实现定时scp的任务
- 拼接dem,山地出现平地
- 【转】9、XAML名称空间详解
- 【转】The underlying connection was closed
- 【转】日邮物流:实现智慧物流,这个云上对了!
- 31模板方法(Template Method)
- (译)你应该知道的jQuery技巧
- JVM核心之JVM运行和类加载全过程
- 用姓名字段统计人数_基于 Wide amp; Deep 网络和 TextCNN 的敏感字段识别
- javase哪部分最难_高中物理哪部分最难?这里有答案和方法!一定要收藏