QT之UDP通信

Posted 菜头大大

tags:

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

前言:前一篇讲了TCP通信,这篇来看看UDP通信。

这里说明一下,UDP通信中分为三种通信分别为单播、组播和广播,下面将一一为大家介绍。

同样的我们都需要在工程文件中添加network

QT       += core gui network

进行UDP通信需要用到的头文件

#include <QUdpSocket>

这里我们把UDP通信分为两个部分写,一个是发送端,另一个是接收端,而发送端中又分为单播、组播和广播三种形式,下面我们先来看看写发送端的代码程序的步骤:

发送端Udpsend的代码:

1、单播

   (1)创建套接字    

QUdpSocket mSocket;
mSocket = new QUdpSocket();

     (2)发送数据到指定的地址和端口号 

mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("192.168.137.1"),6677);
参数:ui->textEdit->toPlainText().toUtf8 要发送的消息
QHostAddress("192.168.137.1") 接收端的ip地址
6677 端口号,要和接收端的一致

 

2、组播,组播和单播的步骤是一样的,只有ip地址处有区别

组播ip地址范围:224.0.0.0-239.255.255.255
例子:mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("224.0.0.100"),6677);

 

3、广播,广播也只有ip地址和单播有区别

广播地址ip:QHostAddress::Broadcast
例子:mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress::Broadcast,6677);

好了,单播、组播和广播的区别应该都了解了,那么我们就来看发送端(udpsend.cpp)的具体代码:

 1 #include "udpsend.h"
 2 #include "ui_udpsend.h"
 3 
 4  UdpSend:: UdpSend(QWidget *parent) :
 5     QMainWindow(parent),
 6     ui(new Ui:: UdpSend)
 7 {
 8     ui->setupUi(this);
 9 
10     //初始化创建QUdpSocket对象
11     mSocket = new QUdpSocket();
12 }
13 
14  UdpSend::~ UdpSend()
15 {
16     delete ui;
17 }
18 
19 void UdpSend::on_sendBt_clicked()
20 {
21     //单播
22    // qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("192.168.137.1"),6677);
23 
24 
25     //组播ip地址范围:224.0.0.0-239.255.255.255
26     //qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("224.0.0.100"),6677);
27 
28     //广播
29     qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress::Broadcast,6677);
30 
31 
32 }

发送端的界面文件我做的很简单,我只做了发送消息框:

 

看完发送端的代码,我们继续来看接收端的代码(Udprecv)

接收端不管是单播、或者组播还是广播代码都是一样的,下面是写接收端代码的步骤:

1、创建套接字

QUdpSocket mSocket;
mSocket = new QUdpSocket();

2、绑定地址和端口号

mSocket->bind(QHostAddress::AnyIPv4,6677);
参数:AnyIPv4  IPv4
     6677  端口号,要和发送端的一致

3、等待数据的到来,利用readyRread()

connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));

4、读数据

readDatagram(char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0)
 参数:
      data:数据
      maxSize:数据的大小
      address:QHostAddress类型的地址
      port:端口号

例子:
void UdpRecv::read_data()
{
    QByteArray array;
    QHostAddress address;
    quint16 port;
    array.resize(mSocket->bytesAvailable());//根据可读数据来设置空间大小
    mSocket->readDatagram(array.data(),array.size(),&address,&port); //读取数据
    ui->listWidget->addItem(array);//显示数据
   //发送反馈数据

}

如果是组播的话还涉及到加入组播和退出组播

加入到组播组  joinMulticastGroup
            例子:mSocket->joinMulticastGroup(QHostAddress("224.0.0.100"));
退出组播组 leaveMulticastGroup 例子: mSocket
->leaveMulticastGroup(QHostAddress("224.0.0.100"));

 

来看看接收端(Udprecv.cpp)具体实现的代码

 1 #include "udprecv.h"
 2 #include "ui_udprecv.h"
 3 
 4 UdpRecv::UdpRecv(QWidget *parent) :
 5     QMainWindow(parent),
 6     ui(new Ui::UdpRecv)
 7 {
 8     ui->setupUi(this);
 9 
10     //创建对象 初始化
11     mSocket = new QUdpSocket();
12 
13     //绑定
14     mSocket->bind(QHostAddress::AnyIPv4,6677);
15     //关联读数据信号readyread
16     connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
17 
18 }
19 
20 UdpRecv::~UdpRecv()
21 {
22     delete ui;
23 }
24 
25 void UdpRecv::read_data()
26 {
27     QByteArray array;
28     QHostAddress address;
29     quint16 port;
30     array.resize(mSocket->bytesAvailable());//根据可读数据来设置空间大小
31     mSocket->readDatagram(array.data(),array.size(),&address,&port); //读取数据
32     ui->listWidget->addItem(array);//显示数据
33    //发送反馈数据
34 
35 }
36 
37 void UdpRecv::on_checkBox_clicked(bool checked)
38 {
39     if(checked)
40     {
41         //加入组播
42         mSocket->joinMulticastGroup(QHostAddress("224.0.0.100"));
43     }
44 
45     else
46     {
47         //退出组播
48         mSocket->leaveMulticastGroup(QHostAddress("224.0.0.100"));
49 
50     }
51 
52 }

接收端的界面文件我只加了显示接收到的信息和选择是否加入组播的选择按钮

 

这是发送端和接收分开来写的,此外我也实现了一下发送端和接收端写到同一个文件中

头文件qudpapp.h中的代码

 1 #ifndef QUDPAPP_H
 2 #define QUDPAPP_H
 3 
 4 #include <QWidget>
 5 #include <QUdpSocket>
 6 namespace Ui {
 7 class QUdpApp;
 8 }
 9 
10 class QUdpApp : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit QUdpApp(QWidget *parent = 0);
16     ~QUdpApp();
17 
18 private slots:
19     void on_sendSigRb_clicked(); //单播旋转轴
20     void on_sendMulRb_clicked();  //组播选择
21     void on_sendBroadRb_clicked(); //广播选择
22     void on_sendBt_clicked(); //发送按钮
23 
24 //===========================================
25     void on_recvCb_clicked(bool checked);  //选择接收
26     void on_recvJoinMulBt_clicked();  //加入组播
27     void on_recvLeaveMulBt_clicked(); //退出组播
28 
29     void on_sendMesEdit_cursorPositionChanged();//检测消息框是否有数据
30     void read_data();
31 
32 private:
33     Ui::QUdpApp *ui;
34     QUdpSocket *mSocket;
35     QHostAddress sendaddrees;
36     QString sendPort;
37 
38 };
39 
40 #endif // QUDPAPP_H
View Code

源文件qudpapp.cpp中的代码

  1 #include "qudpapp.h"
  2 #include "ui_qudpapp.h"
  3 #include <QMessageBox>
  4 QUdpApp::QUdpApp(QWidget *parent) :
  5     QWidget(parent),
  6     ui(new Ui::QUdpApp)
  7 {
  8     ui->setupUi(this);
  9     mSocket = new QUdpSocket();//创建套接字
 10     ui->sendBt->setEnabled(false);
 11 }
 12 
 13 QUdpApp::~QUdpApp()
 14 {
 15     delete ui;
 16 }
 17 
 18 
 19 //==========================发送端====================
 20 //单播选择
 21 void QUdpApp::on_sendSigRb_clicked()
 22 {
 23     if(ui->sendPortEdit->text().isEmpty() || ui->sendSigAddrEdit->text().isEmpty())
 24     {
 25         QMessageBox::warning(this,"提示","请输入单播ip和端口号");
 26         //ui->sendSigRb->setChecked(false);
 27         return;
 28     }
 29     sendaddrees.setAddress( ui->sendSigAddrEdit->text());
 30     sendPort  = ui->sendPortEdit->text();
 31 
 32 }
 33 
 34 //组播选择
 35 void QUdpApp::on_sendMulRb_clicked()
 36 {
 37     if(ui->sendPortEdit->text().isEmpty() || ui->sendMulAddrEdit->text().isEmpty())
 38     {
 39         QMessageBox::warning(this,"提示","请输入组播ip和端口号");
 40         //ui->sendSigRb->setChecked(false);
 41         return;
 42     }
 43    sendaddrees.setAddress( ui->sendMulAddrEdit->text());
 44    sendPort  = ui->sendPortEdit->text();
 45 
 46 }
 47 
 48 //广播选择
 49 void QUdpApp::on_sendBroadRb_clicked()
 50 {
 51     if(ui->sendPortEdit->text().isEmpty() || ui->sendBroadAddrEdit->text().isEmpty())
 52     {
 53         QMessageBox::warning(this,"提示","请输入广播ip和端口号");
 54         //ui->sendSigRb->setChecked(false);
 55         return;
 56     }
 57     sendaddrees.setAddress( ui->sendBroadAddrEdit->text());
 58     sendPort  = ui->sendPortEdit->text();
 59 
 60 }
 61 
 62 //发送按钮
 63 void QUdpApp::on_sendBt_clicked()
 64 {
 65     mSocket->writeDatagram(ui->sendMesEdit->toPlainText().toUtf8(),sendaddrees,sendPort.toInt());
 66 
 67 }
 68 
 69 //检测发送消息对话框中是否有消息
 70 void QUdpApp::on_sendMesEdit_cursorPositionChanged()
 71 {
 72     if(ui->sendMesEdit->toPlainText().isEmpty())
 73     {
 74         ui->sendBt->setEnabled(false);
 75     }
 76     else
 77     {
 78         ui->sendBt->setEnabled(true);
 79     }
 80 
 81 }
 82 
 83 //==========================发送端====================
 84 
 85 
 86 //==========================接收端=====================
 87 
 88 //选择接收
 89 void QUdpApp::on_recvCb_clicked(bool checked)
 90 {
 91     if(ui->recvPortEdit->text().isEmpty())
 92     {
 93         QMessageBox::warning(this,"提示","请输入端口号");
 94         ui->recvCb->setChecked(false);
 95         return;
 96     }
 97     if(checked)
 98     {
 99         mSocket->bind(QHostAddress::AnyIPv4,ui->recvPortEdit->text().toInt());
100         connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
101         ui->recvPortEdit->setEnabled(false);
102     }
103     else
104     {
105         mSocket->close();
106         ui->recvPortEdit->setEnabled(true);
107     }
108 }
109 
110 //加入组播
111 void QUdpApp::on_recvJoinMulBt_clicked()
112 {
113     if(ui->recvMulAddrEdit->text().isEmpty())
114     {
115         QMessageBox::warning(this,"提示","请输入组播ip");
116         return;
117     }
118     if(mSocket->joinMulticastGroup(QHostAddress(ui->recvMulAddrEdit->text()))) //加入组播
119     {
120         ui->recvMulAddr->addItem(ui->recvMulAddrEdit->text());
121     }
122     else
123     {
124         QMessageBox::warning(this,"提示","加入组播失败,请修改ip后继续加入");
125         //return;
126     }
127 
128 }
129 
130 //退出组播
131 void QUdpApp::on_recvLeaveMulBt_clicked()
132 {
133     mSocket->leaveMulticastGroup(QHostAddress(ui->recvMulAddr->currentIndex()));//退出组播地址列表当前的组播
134     ui->recvMulAddr->removeItem(ui->recvMulAddr->currentIndex()); //删除组播地址列表中当前的组播地址
135 }
136 
137 void QUdpApp::read_data()
138 {
139     QByteArray array;
140     array.resize(mSocket->bytesAvailable()); //将接收数据的array设置成为要接收数据的大小
141     QHostAddress recvaddress;
142     quint16 port;
143     mSocket->readDatagram(array.data(),array.size(),&recvaddress,&port); //读取数据
144     ui->recvList->addItem(array);
145 
146 }
147 
148 //==========================接收端=====================
View Code

界面文件qudpapp.ui

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <ui version="4.0">
  3  <class>QUdpApp</class>
  4  <widget class="QWidget" name="QUdpApp">
  5   <property name="geometry">
  6    <rect>
  7     <x>0</x>
  8     <y>0</y>
  9     <width>637</width>
 10     <height>561</height>
 11    </rect>
 12   </property>
 13   <property name="sizePolicy">
 14    <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
 15     <horstretch>0</horstretch>
 16     <verstretch>0</verstretch>
 17    </sizepolicy>
 18   </property>
 19   <property name="windowTitle">
 20    <string>QUdpApp</string>
 21   </property>
 22   <widget class="QWidget" name="layoutWidget">
 23    <property name="geometry">
 24     <rect>
 25      <x>9</x>
 26      <y>9</y>
 27      <width>394</width>
 28      <height>463</height>
 29     </rect>
 30    </property>
 31    <layout class="QVBoxLayout" name="verticalLayout_6">
 32     <item>
 33      <layout class="QHBoxLayout" name="horizontalLayout_9">
 34       <item>
 35        <widget class="QGroupBox" name="groupBox">
 36         <property name="sizePolicy">
 37          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 38           <horstretch>0</horstretch>
 39           <verstretch>0</verstretch>
 40          </sizepolicy>
 41         </property>
 42         <property name="title">
 43          <string>发送端</string>
 44         </property>
 45         <layout class="QVBoxLayout" name="verticalLayout_3">
 46          <property name="spacing">
 47           <number>0</number>
 48          </property>
 49          <property name="leftMargin">
 50           <number>0</number>
 51          </property>
 52          <property name="topMargin">
 53           <number>0</number>
 54          </property>
 55          <property name="rightMargin">
 56           <number>0</number>
 57          </property>
 58          <property name="bottomMargin">
 59           <number>0</number>
 60          </property>
 61          <item>
 62           <layout class="QVBoxLayout" name="verticalLayout_2">
 63            <item>
 64             <layout class="QHBoxLayout" name="horizontalLayout">
 65              <property name="spacing">
 66               <number>0</number>
 67              </property>
 68              <item>
 69               <widget class="QLabel" name="label">
 70                <property name="text">
 71                 <string>端 口 号</string>
 72                </property>
 73               </widget>
 74              </item>
 75              <item>
 76               <widget class="QLineEdit" name="sendPortEdit">
 77                <property name="sizePolicy">
 78                 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 79                  <horstretch>0</horstretch>
 80                  <verstretch>0</verstretch>
 81                 </sizepolicy>
 82                </property>
 83                <property name="placeholderText">
 84                 <string>请输入端口号</string>
 85                </property>
 86               </widget>
 87              </item>
 88             </layout>
 89            </item>
 90            <item>
 91             <layout class="QHBoxLayout" name="horizontalLayout_2">
 92              <property name="

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

QT之UDP通信

QT5之UDP 通信

Qt网络编程之搭建Udp通信单播组播广播

QT学习笔记(13) QT下的UDP通信

qt在windows下的udp通信(最简单)

QT下UDP套接字通信——QUdpSocket 简单使用