日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt之UDP通信

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt之UDP通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、UDP簡介

二、QUdpSocket類

三、UDP服務器

四、UDP客戶端

五、代碼

1.udp服務端

2.udp客戶端


一、UDP簡介

UDP(User Datagram Protocol 即用戶數據報協議)是一個輕量級的,不可靠的,面向數據
報的無連接協議
。由于 UDP 的特性:它不屬于連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用 UDP 較多,因為它們即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。

UDP 通信示意圖如下:

UDP 消息傳送有三種模式,分別是單播廣播組播三種模式。

①單播(unicast): 單播用于兩個主機之間的端對端通信,需要知道對方的 IP 地址與端口

②廣播(broadcast): 廣播 UDP 與單播 UDP 的區別就是 IP 地址不同,廣播一般使用廣播地址
255.255.255.255,將消息發送到在同一廣播(也就是局域網內同一網段) 網絡上的每個主機

注意:本地廣播信息是不會被路由器轉發所以如果一個服務端在win,另外一個客戶端在虛擬機說,這時就需要配置虛擬機的端口轉發,這樣虛擬機才會連得上服務器



③組播(multicast): 組播(多點廣播),也稱為多播,將網絡中同一業務類型主機進行了邏輯上的分組,進行數據收發的時候其數據僅僅在同一分組中進行,其他的主機沒有加入此分組不能收發對應的數據。

在廣域網上廣播的時候,其中的交換機和路由器只向需要獲取數據的主機復制并轉發數據。主機可以向路由器請求加入或退出某個組,網絡中的路由器和交換機有選擇地復制并傳輸數據,將數據僅僅傳輸給組內的主機。多播的這種功能,可以一次將數據發送到多個主機,又能保證不影響其他不需要(未加入組)的主機的其他通信。

注意: 單播一樣和多播是允許在廣域網即 Internet 上進行傳輸的,而廣播僅僅在同一局域網上才能進行


二、QUdpSocket類

QT 的 socket 類之間的關系:?

QUdpSocket 類提供了一個 UDP 套接字。 QUdpSocket 是 QAbstractSocket 的子類,允許發
送和接收 UDP 數據報。

常用API函數

①構造函數

QUdpSocket::QUdpSocket(QObject *parent = Q_NULLPTR)

②如果至少有一個數據報在等待被讀取,則返回true,否則返回false。

bool QUdpSocket::hasPendingDatagrams() const?

③服務器綁定端口

bool bind(const QHostAddress &address, quint16 port = 0, BindMode mode = DefaultForPlatform);

④返回第一個待處理的UDP數據報的大小Byte。如果沒有可用的數據報,該函數返回-1。

qint64 QUdpSocket::pendingDatagramSize() const

⑤接收數據

qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)

接收一個不大于maxSize字節的數據報并將其存儲在data中。發送者的主機地址和端口存儲在*address和*port中(除非指針為0)。成功時返回數據報的大小;否則返回-1。

如果maxSize太小,數據報的其余部分將被丟失。為了避免數據丟失,在試圖讀取數據報之前,應調用pendingDatagramSize()來確定未決數據報的大小。如果maxSize為0,數據報將被丟棄。
?

⑥發送數據

qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)

將數據報以大小的方式發送到端口端口的主機地址。成功時返回發送的字節數,否則返回-1。
數據報總是被寫成一個塊。數據報的最大尺寸與平臺高度相關,但可以低至8192字節。如果數據報太大,這個函數將返回-1,error()將返回DatagramTooLargeError。

一般來說,發送大于512字節的數據報是不利的,因為即使它們被成功發送,在到達最終目的地之前,它們很可能被IP層分割開來。

?三、UDP服務器

?1.創建QUdpSocket對象

mSocket = new QUdpSocket(this);

②綁定地址和端口號

msocket->bind(ip,端口號);

③收到數據時,會觸發readyRead()信號,自定義readPendingDatagrams()進行讀取數據;

connect(msocket,&QUdpSocket::readyRead,?this,&Widget::readPendingDatagrams);

④在while循環中讀取數據,只要有數據,就一直讀取并處理。

? void Server::readPendingDatagrams()
? {
? ? ? while (udpSocket->hasPendingDatagrams()) //數據報等待被讀取

???????{
? ? ? ? ?????????//數據緩沖區

????????????????QByteArray arr;

????????????????//調整緩沖區的大小和收到的數據大小一致 ????????????????

????????????????arr.resize(mSocket->bytesAvailable()); //接收數據

????????????????mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);

? ? ? ? ? ? ? ? //將arr.data轉為字符串即可

????????????????QString str = arr.data();

? ? ? }
? }

通信(先接收) 收到數據會觸發信號readyRead, 通過QUdpSocket對象的readDatagram函數來接收數據 。

readyRead()信號在數據報到達時發出。在這種情況下, hasPendingDatagrams()返回 true。調用 pendingDatagramSize()來獲取第一個待處理數據報的大小,并調用 readDatagram()接收數據。

注意:當接收到readyRead()信號時,一個傳入的數據報應該被讀取,否則這個信號將不會被發送到下一個數據報。

⑤發送數據

qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)

若是廣播消息,與單播消息不同的是將目標 IP 地址換成了廣播地址,一般廣播地址為 255.255.255.255,也可以使用QHostAddress::Broadcast獲取廣播地址

QHostAddress peerAddr = QHostAddress::Broadcast;

只需要將客戶端發送數據:writeDatagramIP地址改為廣播地址即可

四、UDP客戶端

①創建QUdpSocket對象

mSocket = new QUdpSocket(this);

②發送數據到指定的地址和端口號

writeDatagram(數據,接收方ip,接收方端口號);

?發送的數據要是QByteArray類型,Qt中將字符串轉為QByteArray可以使用.toUtf8函數

五、代碼

1.udp服務端

?頭文件

#ifndef UDPSERVER_H #define UDPSERVER_H#include <QWidget> #include <QtNetwork>QT_BEGIN_NAMESPACE namespace Ui { class UdpServer; } QT_END_NAMESPACEclass UdpServer : public QWidget {Q_OBJECTpublic:UdpServer(QWidget *parent = nullptr);~UdpServer();private slots:void on_pushButton_start_clicked();void on_pushButton_send_clicked();void readPendingDatagrams();private:Ui::UdpServer *ui;//Udp服務器QUdpSocket *mSocket;//通信的ip和端口,用于獲取發送者的 IP 和端口QHostAddress addr;quint16 port; }; #endif // UDPSERVER_H

源文件

#include "udpserver.h" #include "ui_udpserver.h"UdpServer::UdpServer(QWidget *parent): QWidget(parent), ui(new Ui::UdpServer) {ui->setupUi(this); }UdpServer::~UdpServer() {delete ui; }//啟動 void UdpServer::on_pushButton_start_clicked() {//1.創建QUdpSocket對象mSocket = new QUdpSocket(this);//2.連接接收數據信號和槽QObject::connect(mSocket,&QUdpSocket::readyRead,this,&UdpServer::readPendingDatagrams);//3.綁定mSocket->bind(QHostAddress::Any,ui->spinBox->value());//連接回車發送的信號和槽QObject::connect(ui->lineEdit,&QLineEdit::returnPressed,this,&UdpServer::on_pushButton_send_clicked);//禁止端口號和啟動按鈕ui->spinBox->setEnabled(false);ui->pushButton_start->setEnabled(false); }void UdpServer::on_pushButton_send_clicked() {//獲取發送的數據QByteArray arr = ui->lineEdit->text().toUtf8();//發送mSocket->writeDatagram(arr,addr,port);//顯示發送的內容ui->textBrowser->insertPlainText("send:"+QString(arr)+"\n");//情況lineEditui->lineEdit->clear(); }void UdpServer::readPendingDatagrams() {//數據緩沖區QByteArray arr;while(mSocket->hasPendingDatagrams()){//調整緩沖區的大小和收到的數據大小一致arr.resize(mSocket->bytesAvailable());//接收數據mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);//顯示ui->textBrowser->insertPlainText(addr.toString()+":"+QString(arr)+"\n");//使能發送按鈕和編輯框ui->lineEdit->setEnabled(true);ui->pushButton_send->setEnabled(true);} }

2.udp客戶端

頭文件

#ifndef UDPCILENT_H #define UDPCILENT_H#include <QWidget> #include <QtNetwork>QT_BEGIN_NAMESPACE namespace Ui { class UdpCilent; } QT_END_NAMESPACEclass UdpCilent : public QWidget {Q_OBJECTpublic:UdpCilent(QWidget *parent = nullptr);~UdpCilent();private slots:void on_pushButton_send_clicked();void readPendingDatagrams();private:Ui::UdpCilent *ui;//UDP客戶端QUdpSocket *mSocket; }; #endif // UDPCILENT_H

?源文件

#include "udpcilent.h" #include "ui_udpcilent.h"UdpCilent::UdpCilent(QWidget *parent): QWidget(parent), ui(new Ui::UdpCilent) {ui->setupUi(this);//1.創建QUdpSocketmSocket = new QUdpSocket(this);//2.通信(接收)QObject::connect(mSocket,&QUdpSocket::readyRead,this,&UdpCilent::readPendingDatagrams);//連接回車發送的信號和槽QObject::connect(ui->lineEdit_send,&QLineEdit::returnPressed,this,&UdpCilent::on_pushButton_send_clicked);}UdpCilent::~UdpCilent() {delete ui; }//發送 void UdpCilent::on_pushButton_send_clicked() {//獲取發送的數據QByteArray arr = ui->lineEdit_send->text().toUtf8();//發送//mSocket->writeDatagram(arr,QHostAddress(ui->lineEdit_ip->text()),ui->spinBox->value());mSocket->writeDatagram(arr,QHostAddress::Broadcast,ui->spinBox->value());//顯示發送的內容ui->textBrowser->insertPlainText("send:"+QString(arr)+"\n");//情況lineEditui->lineEdit_send->clear(); }void UdpCilent::readPendingDatagrams() {QHostAddress addr; //用于獲取發送者的 IP 和端口quint16 port;//數據緩沖區QByteArray arr;while(mSocket->hasPendingDatagrams()){//調整緩沖區的大小和收到的數據大小一致arr.resize(mSocket->bytesAvailable());//接收數據mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);//顯示ui->textBrowser->insertPlainText(addr.toString()+":"+QString(arr)+"\n");} }

結果:?
?

?

總結

以上是生活随笔為你收集整理的Qt之UDP通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。