QT -- UdpSocket通信实例,使用Qt的UDP通信协议,实现局域网组播通信软件功能
使用Qt - udp通信方式,构建局域网聊天通信软件实例
- 1.简介效果
- 2.项目设计
- 1)流程图
- 2)项目构建
- 3)界面构建
- 4)代码设计
- a.widget.h
- b.widget.cpp
- c.secondwidget.h
- d.secondwidget.cpp
- 3.源代码
- widget.h
- widget.cpp
- secondwidget.h
- secondwidget.cpp
- 5.源文件下载
1.简介效果
在之前的文章中,介绍了TCP协议在Qt中的应用实现方式传送门,TCP通信方式是面向对象,可靠的连接服务。而与之对应的是不可靠,无连接的UDP通信协议,两者是TCP/IP协议簇中较为常用的两者通信方式。
之前的博文中,实现了利用Qt调用TCP协议的局域网通信聊天,而这篇博文将介绍UDP协议在Qt中的简单运用,其想要达到的效果如下。
使用UDP就和TCP不同的是,UDP协议只管发,实用于及时通信领域,它只管发送,不管对方是否收到,但因为其传输效率高效,消耗资源小,所以尝尝结合于TCP协议一同使用在通信连接中。我们最常用的就是QQ,QQ采用TCP连接来保持在线状态,使其连接至上层的腾讯服务器,而聊天发送消息功能大都采用UDP方式,当UDP协议不能正常转发的时候,就会采用TCP协议进行发送,所以,TCP和UDP协议常常一同使用。
2.项目设计
1)流程图
UDP协议流程图,如下图所示,经此流程图后,我们可以清晰的知道,UDP是如何通信工作,并进行调用。
UDP协议没有明确的客户端和服务端可言,只要绑定了对应的IP地址和端口号,就可以进行通信,如很多的组播软件,可以使绑定同一个IP。使得多个端口号的客户在此IP下进行通信和数据传输。
2)项目构建
新建为widget项目,构建如下所示项目树
3)界面构建
两个界面设计构建如下
- 界面一 - secondwdiget
- 界面二 - widget
使用行编辑框和文本编辑框构建简单的界面如上所示。
4)代码设计
和Qt使用TCP一样,想要在Qt中使用网络编程的包。需要在.pro工程文件里面添加如下代码
QT += network
a.widget.h
首先还是需要添加Qt中封装好的UDP的头文件
#include <QUdpSocket>
之后对其进行初始化声明,并定义一个处理消息队列的槽函数,用以在UDP通信套接字连接后发送消息,之后便是重写事件过滤器用以响应键盘Enter键的输入,具体代码如下
public:void dealMsg(); //槽函数,处理对方发过来的数据
protected:bool eventFilter(QObject *target, QEvent *event);//事件过滤器
private:QUdpSocket *udpSocket;
b.widget.cpp
在执行文件中,对构建函数中的udpSocket分配动态空间,当连接好之后,自动并触发连接的槽函数。
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);this->resize(450,300);this->setWindowTitle("服务器端口:8888");udpSocket = new QUdpSocket(this);//绑定端口号udpSocket->bind(8888);//udpSocket->bind(QHostAddress::AnyIPv4,8888); //必须是主机的ipv4类通信方式,以及本机的ip地址//当对方发送数据过来。自动触发readyRead()connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::dealMsg);//键盘Enter键设置ui->ButtonSend->setFocus();ui->ButtonSend->setDefault(true);ui->textEditShow->installEventFilter(this);//设置完后自动调用其eventFilter函数}
之后便是对自定义处理消息队列的槽函数进行函数实现
void Widget::dealMsg()
{//读取对方发送的内容char buf[1024] = {0}; //内容QHostAddress cliAddr; //对方地址quint16 port; //对方端口qint64 len = udpSocket->readDatagram(buf,sizeof(buf),&cliAddr,&port);//添加时间QTime cur_time = QTime::currentTime();QString time_info = cur_time.toString("hh:mm:ss");if(len >0){//获取到文本格式化 如 [192.168.1.1 : 8888]aaaa 的格式QString str = QString("[%1:%2] %3 [%4]").arg(cliAddr.toString()).arg(port).arg(buf).arg(time_info);//ui->textEditShow->setText(str);ui->textEditShow->append(str);}}
然后便是对事件过滤器的函数实现
bool Widget::eventFilter(QObject *target, QEvent *event)
{if(target == ui->textEditShow) //对象为需要发送的焦点{if(event->type() == QEvent::KeyPress)//回车键{QKeyEvent *k = static_cast<QKeyEvent *>(event);if(k->key() == Qt::Key_Return){on_ButtonSend_clicked();return true;}}}return QWidget::eventFilter(target,event);
}
最后是点击发送按钮,获取编辑框中的内容,使用通信套接字,将其发送给绑定特定端口号的一方
void Widget::on_ButtonSend_clicked()
{//获取对方的ip和端口QString ip = ui->lineEditIp->text();qint16 port = ui->lineEditPort->text().toInt();//获取编辑区内容QString str = ui->textEditShow->toPlainText();//给指定的ip发送数据udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);ui->textEditShow->clear();}
c.secondwidget.h
添加socket头文件方法和声明,以及消息队列处理函数,和键盘响应函数同上
public:void dealMsg2(); //槽函数,处理对方发过来的数据
protected:bool eventFilter(QObject *target, QEvent *event);//事件过滤器
private:QUdpSocket *udpSocket;
d.secondwidget.cpp
构造函数和第一个界面有一点点不同,如下
SecondWidget::SecondWidget(QWidget *parent) :QWidget(parent),ui(new Ui::SecondWidget)
{ui->setupUi(this);this->resize(450,300);this->setWindowTitle("服务器端口2:9999");udpSocket2 = new QUdpSocket(this);//绑定udpSocket2->bind(9999);connect(udpSocket2,&QUdpSocket::readyRead,this,&SecondWidget::dealMsg2);ui->ButtonSend2->setFocus();ui->ButtonSend2->setDefault(true);//ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);ui->textEditShow2->installEventFilter(this);//设置完后自动调用其eventFilter函数
}
其他的函数实现方式和第一个界面相同,这类不再赘述。待正确编译之后,即可实现这样的效果
- 注意:Qt中UDP通信只需要在同一个ip下(需要绑定自己电脑上的ip,使用ipconfig命令查看该电脑的ipv4的地址),绑定对应的端口号。即可进行通信连接
3.源代码
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QUdpSocket>namespace Ui {class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();void dealMsg(); //槽函数,处理对方发过来的数据
protected:bool eventFilter(QObject *target, QEvent *event);//事件过滤器private slots:void on_ButtonSend_clicked();void on_ButtonClose_clicked();private:Ui::Widget *ui;private:QUdpSocket *udpSocket;
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>
#include <QDebug>
#include <QTime>
#include <QKeyEvent>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);this->resize(450,300);this->setWindowTitle("服务器端口:8888");udpSocket = new QUdpSocket(this);//绑定端口号udpSocket->bind(8888);//udpSocket->bind(QHostAddress::AnyIPv4,8888); //必须是主机的ipv4类通信方式,以及本机的ip地址//当对方发送数据过来。自动触发readyRead()connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::dealMsg);ui->ButtonSend->setFocus();ui->ButtonSend->setDefault(true);ui->textEditShow->installEventFilter(this);//设置完后自动调用其eventFilter函数}Widget::~Widget()
{delete ui;
}void Widget::dealMsg()
{//读取对方发送的内容char buf[1024] = {0}; //内容QHostAddress cliAddr; //对方地址quint16 port; //对方端口qint64 len = udpSocket->readDatagram(buf,sizeof(buf),&cliAddr,&port);QTime cur_time = QTime::currentTime();QString time_info = cur_time.toString("hh:mm:ss");if(len >0){//获取到文本格式化 [192.168.1.1 : 8888]aaaaQString str = QString("[%1:%2] %3 [%4]").arg(cliAddr.toString()).arg(port).arg(buf).arg(time_info);//ui->textEditShow->setText(str);ui->textEditShow->append(str);}}bool Widget::eventFilter(QObject *target, QEvent *event)
{if(target == ui->textEditShow){if(event->type() == QEvent::KeyPress)//回车键{QKeyEvent *k = static_cast<QKeyEvent *>(event);if(k->key() == Qt::Key_Return){on_ButtonSend_clicked();return true;}}}return QWidget::eventFilter(target,event);
}void Widget::on_ButtonSend_clicked()
{//获取对方的ip和端口QString ip = ui->lineEditIp->text();qint16 port = ui->lineEditPort->text().toInt();//获取编辑区内容QString str = ui->textEditShow->toPlainText();//给指定的ip发送数据udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);ui->textEditShow->clear();}void Widget::on_ButtonClose_clicked()
{udpSocket->disconnectFromHost();udpSocket->close();qDebug() << "主服务器连接断开!";this->close();}
secondwidget.h
#ifndef SECONDWIDGET_H
#define SECONDWIDGET_H#include <QWidget>
#include <QUdpSocket>namespace Ui {class SecondWidget;
}class SecondWidget : public QWidget
{Q_OBJECTpublic:explicit SecondWidget(QWidget *parent = nullptr);~SecondWidget();void dealMsg2(); //消息队列处理
protected:bool eventFilter(QObject *target, QEvent *event);//事件过滤器private slots:void on_ButtonSend2_clicked();void on_ButtonClose2_clicked();private:Ui::SecondWidget *ui;
private:QUdpSocket *udpSocket2;};#endif // SECONDWIDGET_H
secondwidget.cpp
#include "secondwidget.h"
#include "ui_secondwidget.h"
#include <QHostAddress>
#include <QDebug>
#include <QTime>
#include <QKeyEvent>SecondWidget::SecondWidget(QWidget *parent) :QWidget(parent),ui(new Ui::SecondWidget)
{ui->setupUi(this);this->resize(450,300);this->setWindowTitle("服务器端口2:9999");udpSocket2 = new QUdpSocket(this);//绑定udpSocket2->bind(9999);connect(udpSocket2,&QUdpSocket::readyRead,this,&SecondWidget::dealMsg2);ui->ButtonSend2->setFocus();ui->ButtonSend2->setDefault(true);//ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return);ui->textEditShow2->installEventFilter(this);//设置完后自动调用其eventFilter函数
}SecondWidget::~SecondWidget()
{delete ui;
}void SecondWidget::dealMsg2()
{//读取对方发送的内容char buf[1024] = {0}; //内容QHostAddress cliAddr; //对方地址quint16 port; //对方端口qint64 len = udpSocket2->readDatagram(buf,sizeof(buf),&cliAddr,&port);QTime cur_time = QTime::currentTime();QString time_info = cur_time.toString("hh:mm:ss");if(len >0){//获取到文本格式化 [192.68.1.144 : 8888]aaaaQString str = QString("[%1:%2] %3 [%4]").arg(cliAddr.toString()).arg(port).arg(buf).arg(time_info);//ui->textEditShow2->setText(str);ui->textEditShow2->append(str);}
}bool SecondWidget::eventFilter(QObject *target, QEvent *event)
{if(target == ui->textEditShow2){if(event->type() == QEvent::KeyPress)//回车键{QKeyEvent *k = static_cast<QKeyEvent *>(event);if(k->key() == Qt::Key_Return){on_ButtonSend2_clicked();return true;}}}return QWidget::eventFilter(target,event);
}void SecondWidget::on_ButtonSend2_clicked()
{//获取对方的ip和端口QString ip = ui->lineEditIp2->text();qint16 port = ui->lineEditPort2->text().toInt();//获取编辑区内容QString str = ui->textEditShow2->toPlainText();//给指定的ip发送数据udpSocket2->writeDatagram(str.toUtf8(),QHostAddress(ip),port);ui->textEditShow2->clear();
}void SecondWidget::on_ButtonClose2_clicked()
{udpSocket2->disconnectFromHost();udpSocket2->close();qDebug() << "断开连接!";this->close();}
5.源文件下载
如果感兴趣想要源文件的,请移至传送门源代码文件下载
QT -- UdpSocket通信实例,使用Qt的UDP通信协议,实现局域网组播通信软件功能相关推荐
- 网络编程-Socket套接字(TCP、UDP、广播和组播通信)
socket套接字 socket是一个编程接口(网络编程接口) 作用是用来实现网络上不同的主机的应用进程之间进行双向通信 套接字是一种特殊的文件描述符 也就意味着我们使用套接字实现网络通信的时候可以用 ...
- linux UDP实现广播和组播
广播 广播很简单,原理不解释了,这里实现的重点在于: 1.对服务器端的套接字使用setsockopt函数开放广播权限 2.指定要发送的IP(广播地址)+端口号 3.客户端必须显式绑定端口号(和2的端口 ...
- 基于UDP的多播(组播)文件传输
此次的课程设计通过借鉴网上的信息(前人种树后人乘凉,感谢在网上分享的大佬们)然后自己再次修改调试完成. 步入正题吧 主要代码: public class MULTICAST {private Stri ...
- 浅谈 Qt 中 UDP 之 UdpSocket通信实例
浅谈 Qt 中 UDP 写这篇博客的原因是Java大作业最近完成了一个简单的聊天室.也是基于UDP的.正好我们在学习Qt.所以我想能不能再qt中同样实现这样一个问题.于是我进行的代码的编辑.以及其他 ...
- java网络编程 UDP通信协议实现局域网内文件的发送和接收
要实现两台内网下的机子进行通信,首先得知道接收方的内网IP,获取IP的方式:可以打开任务管理器的以太网进行查看: 如下 也可以通过 win+r 输入cmd ,然后输入 ipconfig 回车 进行 ...
- Qt udp组播Qt udp组播
代码部分: #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLabel> ...
- c#Socket通信实例
一.Socket通信简介 1.按惯例先来介绍下socket Windows中的很多东西都是从Unix领域借鉴过来的,Socket也是一样.在Unix中,socket代表了一种文件描述符(在Unix中一 ...
- 虚拟机无法接受组播消息_基于UDP的组播通信
基于UDP的组播通信 在Java实现基于UDP协议的发送端与接收端通信中,我们可以知道它的一些主要操作: 在发送端:1,创建绑定指定端口的发送接口:DatagramSocket(port) 2,创建绑 ...
- [转]UDP(udp通信、广播、组播),本地套接字
转发参考链接: [陈宸-研究僧] https://blog.csdn.net/qq_35883464/article/details/103741461 [Alliswell_WP] https:// ...
- c/c++:UDP(udp通信、广播、组播),本地套接字
目录 1. udp 1.1 udp通信流程 1.2 操作函数 send.sendto recv.recvfrom 2. 广播 2.1 广播通信流程 2.2 设置广播属性函数:setsockopt 2. ...
最新文章
- java简介 ppt 精_《JAVA》5选择结构精篇课件.ppt
- embedding层和全连接层的区别是什么 一般说embedding层,实现方式就是一个没有bias的fc层
- ECharts简单入门demo
- 德意志银行CEO:将逐渐用 AI 替代人工,银行决不会一成不变 凤凰科技 09-08 20:41 原标题:德意志银行CEO:将逐渐用 AI 替代人工,银行决不会一成不变 雷锋网AI金融评论报道,外媒i
- 操作系统:分享10个经常用的cmd命令
- java bufferarray_Java中的ByteBuffer array()方法
- python动态方法_python中的动态方法生成
- 因为一次宕机,终于搞透了 Kafka 高可用原理!
- 设计灵感|如何让你的海报更吸睛?
- 【Shell脚本】TDS离线备份还原
- 类库如何读取配置文件(app.config)?
- linux用户登录失败,锁定用户
- go语言阶段综合练习--家庭收支软件的示例--过程版本
- Marvelous Designer 服装设计与模拟
- HTML 网页自动刷新
- c语言中求圆台体积公式,圆台体积公式是什么
- 2022年手机CPU性能天梯图排行榜 手机处理器排行榜 2022
- oracle 大于当天时间_ORACLE日期时间函数大全
- element ui el-table单元格按需合并
- python数据分析:商品数据化运营(上)——知识点
热门文章
- 用CIL写程序:从“call vs callvirt”看方法调用
- Hadoop学习目录导航
- win10怎么用记事本打开html文件,Win10系统怎么打开记事本
- 多功能函数计算器(MATLAB实现)
- 调试过程中需要使用的工具
- kepware odata 接口访问地址
- 图书馆占座系统(SSM,JQUERY-EASYUI,MYSQL)
- 清华linux网络编程视频,清华大学视频课件:基于Linux的C++(自主模式)
- 初学必看,NFine框架结构加MVC快速开发平台登录流程梳理(附源码)
- 速达财务管理软件使用方法