zoukankan      html  css  js  c++  java
  • 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"));

    测试:

  • 相关阅读:
    C++操作Kafka使用Protobuf进行跨语言数据交互
    聊聊Disruptor 和 Aeron 这两个开源库
    DTrace arg0-kernel mode and arg1-user mode
    top
    how to write your first linux device driver
    how to compile and replace ubuntu kernel
    linux du
    c++ rvo vs std::move
    【Android】wifi开发
    无线局域网络 WIFI/WAPI/WLAN区别浅析
  • 原文地址:https://www.cnblogs.com/mrlayfolk/p/13285766.html
Copyright © 2011-2022 走看看