Qt-udp通信

Posted mrlayfolk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt-udp通信相关的知识,希望对你有一定的参考价值。

1  简介

参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=61

说明:UDP是面向无连接的,客户端并不与服务器不建立连接,直接向服务器发送数据,服务器端也不从客户端接收连接,只负责调用接收函数,等待客户端连接的到达。

udp通信模型如下:

技术图片

 (1)服务器端

1)创建套接字;

2)绑定套接字;

3)接收或发送数据;

4)关闭连接。

(2)客户端

1)创建套接字;

2)接收或发送数据;

3)关闭连接。

2  测试说明

(1)基本udp测试

功能:创建一个窗口,使用127.0.0.1:8888进行回环测试,自发自收。

实现步骤:

创建套接字并绑定端口,不指定ip:

1     QUdpSocket *udpsocket = NULL;
2     //创建套接字,指定父对象
3     udpsocket = new QUdpSocket(this);
4     //绑定
5     udpsocket->bind(8888);

送数据:

 1     //先获取对方的ip和端口
 2     QString ip = ui->lineEdit_ip->text();
 3     qint16 port = ui->lineEdit_port->text().toInt();
 4     //获取编辑区内容
 5     QString str = ui->textEdit_send->toPlainText();
 6     if (str.isEmpty()) {
 7         return;
 8     }
 9     //给指定的IP发送数据
10     udpsocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);

接收数据:

 1     //当对方成功发送数据过来,会自动触发readyRead()信号
 2     connect(udpsocket, &QUdpSocket::readyRead,
 3         [=](){
 4             //读取对方发送的数据
 5             char buf[1024] = {0};
 6             QHostAddress cli_addr;  //对方地址
 7             quint16 port;  //对方端口
 8             qint64 len = udpsocket->readDatagram(buf, sizeof(buf), &cli_addr, &port);
 9             if (len > 0) {
10                 //格式化[192.168.2.2:8888]aaaa
11                 QString str = QString("[%1:%2] %3").arg(cli_addr.toString()).arg(port).arg(buf);
12                 //给编辑区设置内容
13                 ui->textEdit_recv->append(str);
14             }
15         }
16     );

完整代码如下:

widget.h

技术图片
 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 #include <QUdpSocket>
 6 
 7 namespace Ui {
 8 class Widget;
 9 }
10 
11 class Widget : public QWidget
12 {
13     Q_OBJECT
14 
15 public:
16     explicit Widget(QWidget *parent = 0);
17     ~Widget();
18 
19 private slots:
20     void on_pushButton_send_clicked();
21 
22     void on_pushButton_close_clicked();
23 
24 private:
25     Ui::Widget *ui;
26     QUdpSocket *udpsocket = NULL;
27 };
28 
29 #endif // WIDGET_H
View Code

widget.cpp

技术图片
 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include <QHostAddress>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10     setWindowTitle("服务器端口为:8888");
11 
12     //创建套接字,指定父对象
13     udpsocket = new QUdpSocket(this);
14     //绑定
15     udpsocket->bind(8888);
16     //当对方成功发送数据过来,会自动触发readyRead()信号
17     connect(udpsocket, &QUdpSocket::readyRead,
18         [=](){
19             //读取对方发送的数据
20             char buf[1024] = {0};
21             QHostAddress cli_addr;  //对方地址
22             quint16 port;  //对方端口
23             qint64 len = udpsocket->readDatagram(buf, sizeof(buf), &cli_addr, &port);
24             if (len > 0) {
25                 //格式化[192.168.2.2:8888]aaaa
26                 QString str = QString("[%1:%2] %3").arg(cli_addr.toString()).arg(port).arg(buf);
27                 //给编辑区设置内容
28                 ui->textEdit_recv->append(str);
29             }
30         }
31     );
32 }
33 
34 Widget::~Widget()
35 {
36     delete ui;
37 }
38 
39 void Widget::on_pushButton_send_clicked()
40 {
41     //先获取对方的ip和端口
42     QString ip = ui->lineEdit_ip->text();
43     qint16 port = ui->lineEdit_port->text().toInt();
44     //获取编辑区内容
45     QString str = ui->textEdit_send->toPlainText();
46     if (str.isEmpty()) {
47         return;
48     }
49     //给指定的IP发送数据
50     udpsocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
51 }
52 
53 void Widget::on_pushButton_close_clicked()
54 {
55     close();
56 }
View Code

运行测试:

技术图片

(2)UDP广播

概念:使用UDP广播,局域网内的其它UDP用户全部可以收到广播的消息。UDP广播只能在局域网范围内使用。

Qt中在使用writeDatagram()函数发送数据的时候,将第二个参数设置为广播地址QHostAddress::Broadcast就表示UDP广播。

技术图片

(3)UDP组播

当我们需要发送消息给某些特定用户,或者只接收某些特定用户的消息时,可以使用组播进行实现。

组播地址有:

  • 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
  • 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
  • 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
  • 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。

Qt中注册加入到组播地址需要使用QUdpSocket类的成员函数joinMulticastGroup()。

更改上面的代码的bind和加入joinMulticastGroup()函数:

1     //用主播,主要使用ipv4地址
2     udpsocket->bind(QHostAddress::AnyIPv4, 8888);
3     //加入某个组播,组播地址是D类地址
4     udpsocket->joinMulticastGroup(QHostAddress("224.0.0.2"));

测试:

技术图片

以上是关于Qt-udp通信的主要内容,如果未能解决你的问题,请参考以下文章

与另一个片段通信的片段接口

无法通过接口获取与片段通信的活动

如何在嵌套片段内的两个子片段之间进行通信

与 viewpager 内的片段的父片段通信

片段通信问题(尝试调用虚方法)

片段和服务器之间的通信问题