02 UDP在Qt中的實(shí)現(xiàn)

1.什么是UDP隶债?

以下解釋來自百度百科:https://baike.baidu.com/item/UDP

UDP 是User Datagram Protocol的簡(jiǎn)稱默赂, 中文名是用戶數(shù)據(jù)報(bào)協(xié)議旱函,是OSI(Open System Interconnection耙蔑,開放式系統(tǒng)互聯(lián)) 參考模型中一種無(wú)連接的傳輸層協(xié)議吕嘀,提供面向事務(wù)的簡(jiǎn)單不可靠信息傳送服務(wù)瑟俭,IETF RFC 768是UDP的正式規(guī)范翎卓。UDP在IP報(bào)文的協(xié)議號(hào)是17。

UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議摆寄,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包失暴,是一種無(wú)連接的協(xié)議坯门。在OSI模型中,在第四層——傳輸層逗扒,處于IP協(xié)議的上一層古戴。UDP有不提供數(shù)據(jù)包分組、組裝和不能對(duì)數(shù)據(jù)包進(jìn)行排序的缺點(diǎn)矩肩,也就是說现恼,當(dāng)報(bào)文發(fā)送之后,是無(wú)法得知其是否安全完整到達(dá)的黍檩。UDP用來支持那些需要在計(jì)算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用叉袍。包括網(wǎng)絡(luò)視頻會(huì)議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用UDP協(xié)議。UDP協(xié)議從問世至今已經(jīng)被使用了很多年刽酱,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋喳逛,但是即使是在今天UDP仍然不失為一項(xiàng)非常實(shí)用和可行的網(wǎng)絡(luò)傳輸層協(xié)議。

與所熟知的TCP(傳輸控制協(xié)議)協(xié)議一樣棵里,UDP協(xié)議直接位于IP(網(wǎng)際協(xié)議)協(xié)議的頂層润文。根據(jù)OSI(開放系統(tǒng)互連)參考模型,UDP和TCP都屬于傳輸層協(xié)議殿怜。UDP協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)包的形式典蝌。一個(gè)典型的數(shù)據(jù)包就是一個(gè)二進(jìn)制數(shù)據(jù)的傳輸單位。每一個(gè)數(shù)據(jù)包的前8個(gè)字節(jié)用來包含報(bào)頭信息头谜,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)骏掀。

2.新建一個(gè)工程

  • Projects->New Project->Application->Qt Widgets Application->Choose,見Fig2.1乔夯。
  • setNametoUDP砖织,藍(lán)后一路Next直到Finish,見Fig2.2末荐。
  • 工程結(jié)構(gòu)中各個(gè)文件夾放的東西:Headers--頭文件、Source--源文件新锈、Forms--界面文件甲脏,見Fig2.3。
Fig2.1 Creat a New Project

Fig2.2 Rename it to UDP

Fig2.3 My UDP Project

3.編輯界面

  • Edit\Projects\UDP\Forms下雙擊mainwindow.ui妹笆,進(jìn)入界面設(shè)計(jì)块请,見圖Fig3.1。
  • Display Widgets中拖兩個(gè)Label過來拳缠,并依次雙擊將內(nèi)容更改為對(duì)方的IP墩新、對(duì)方的端口,見圖Fig3.2窟坐。
  • 繼續(xù)在Input Widgets拉兩個(gè)Line EditText Edit一個(gè)過來海渊,在Buttons中拖兩個(gè)Push Button绵疲,并按Fig3.3中調(diào)整布局和在右側(cè)屬性欄中更改各個(gè)控件的名字。
    Fig3.1 mainwindows.ui
Fig3.2 Setting the Labels
Fig3.3 Adding and Setting the Controllers

4.更改UDP.pro文件

  • Edit\UDP中雙擊UDP.pro臣疑。
  • 將第七行QT += core gui更改為QT += core gui network盔憨,整個(gè)文件如下:
#-------------------------------------------------
#
# Project created by QtCreator 2019-03-17T06:00:09
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = UDP
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

  • 點(diǎn)下Fig4.1左下角的榔頭,編譯不運(yùn)行一下讯沈。


    Fig4.1 Click Biuld Project

5.編輯mainwindow.h頭文件

  • 內(nèi)容如下
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QUdpSocket> //UDP套接字

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
    void dealMsg(); // 槽函數(shù),處理信息

private:
    Ui::MainWindow *ui;
    QUdpSocket * udpSocket; //udp指針
};

#endif // MAINWINDOW_H

6.編輯mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 分配空間郁岩,指定父對(duì)象
    udpSocket = new QUdpSocket(this);

    // 綁定
    udpSocket->bind(8888);

    // 獲取本機(jī)ip
    QString strIpAddress = QHostAddress(QHostAddress::LocalHost).toString();

    // 設(shè)置窗口的標(biāo)題
    QString title = QString("服務(wù)器IP:%1,端口為:8888").arg(strIpAddress);
    setWindowTitle(title);

    // 當(dāng)對(duì)方成功發(fā)送數(shù)據(jù)時(shí)
    // 自動(dòng)觸發(fā) readyRead()
    connect(udpSocket, &QUdpSocket::readyRead, this, &MainWindow::dealMsg);
}

// 信息處理函數(shù)
void MainWindow::dealMsg()
{
    char buf[512] = {0};
    QHostAddress clientAddr;
    quint16 port;

    // 讀取對(duì)方發(fā)送的內(nèi)容
    qint64 len = udpSocket->readDatagram(buf, sizeof(buf), &clientAddr, &port);
    if (len > 0) {
        QString str = QString("[%1:%2] %3")
                .arg(clientAddr.toString())
                .arg(port)
                .arg(buf);

        // 設(shè)置顯示內(nèi)容
        ui->textEdit_Msg->setText(str);

    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

7.0給PushButton_Send增加點(diǎn)擊響應(yīng)事件

  • mainwindow.ui中對(duì)send右擊選擇Go to slot->clicked(),見圖Fig7.1和Fig7.2
  • 自動(dòng)跳轉(zhuǎn)到mainwindow.cpp
  • 新增一個(gè)響應(yīng)單擊事件的槽函數(shù)如下:
void MainWindow::on_pushButton_Send_clicked()
{
    // 獲取接受方IP
    QString ip = ui->lineEdit_IP->text();
    qint16 port = ui->lineEdit_Port->text().toInt();

    // 獲取編輯區(qū)內(nèi)容
    QString str = ui->textEdit_Msg->toPlainText();

    // 給指定IP發(fā)送數(shù)據(jù)
    udpSocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
}
Fig7.1 Right Click Send
Fig7.2 Go to slot->clicked()
  • 最終的mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 分配空間,指定父對(duì)象
    udpSocket = new QUdpSocket(this);

    // 綁定
    udpSocket->bind(8888);

    // 獲取本機(jī)ip
    QString strIpAddress = QHostAddress(QHostAddress::LocalHost).toString();

    // 設(shè)置窗口的標(biāo)題
    QString title = QString("服務(wù)器IP:%1,端口為:8888").arg(strIpAddress);
    setWindowTitle(title);

    // 當(dāng)對(duì)方成功發(fā)送數(shù)據(jù)時(shí)
    // 自動(dòng)觸發(fā) readyRead()
    connect(udpSocket, &QUdpSocket::readyRead, this, &MainWindow::dealMsg);
}

// 信息處理函數(shù)
void MainWindow::dealMsg()
{
    char buf[512] = {0};
    QHostAddress clientAddr;
    quint16 port;

    // 讀取對(duì)方發(fā)送的內(nèi)容
    qint64 len = udpSocket->readDatagram(buf, sizeof(buf), &clientAddr, &port);
    if (len > 0) {
        QString str = QString("[%1:%2] %3")
                .arg(clientAddr.toString())
                .arg(port)
                .arg(buf);

        // 設(shè)置顯示內(nèi)容
        ui->textEdit_Msg->setText(str);

    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_Send_clicked()
{
    // 獲取接受方IP
    QString ip = ui->lineEdit_IP->text();
    qint16 port = ui->lineEdit_Port->text().toInt();

    // 獲取編輯區(qū)內(nèi)容
    QString str = ui->textEdit_Msg->toPlainText();

    // 給指定IP發(fā)送數(shù)據(jù)
    udpSocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
}

8.0測(cè)試

  • 保存一下所有文件
  • <F5>運(yùn)行,見圖Fig8.1
  • 在IP和端口中填入本機(jī)的也是可以收到的或者你再開一臺(tái)電腦一起測(cè)試,我是直接填本機(jī)的,見圖Fig8.2
  • 點(diǎn)擊<Send>后,如圖Fig8.3,證明發(fā)送成功
Fig8.1 運(yùn)行效果
Fig8.2 填入?yún)?shù)和數(shù)據(jù)
Fig8.3 發(fā)送成功
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缺狠,一起剝皮案震驚了整個(gè)濱河市问慎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挤茄,老刑警劉巖蝴乔,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驮樊,居然都是意外死亡薇正,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門囚衔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挖腰,“玉大人,你說我怎么就攤上這事练湿『锫兀” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵肥哎,是天一觀的道長(zhǎng)辽俗。 經(jīng)常有香客問我,道長(zhǎng)篡诽,這世上最難降的妖魔是什么崖飘? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮杈女,結(jié)果婚禮上朱浴,老公的妹妹穿的比我還像新娘。我一直安慰自己达椰,他們只是感情好翰蠢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著啰劲,像睡著了一般梁沧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝇裤,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天廷支,我揣著相機(jī)與錄音频鉴,去河邊找鬼。 笑死酥泞,一個(gè)胖子當(dāng)著我的面吹牛砚殿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芝囤,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼似炎,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了悯姊?” 一聲冷哼從身側(cè)響起羡藐,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悯许,沒想到半個(gè)月后仆嗦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡先壕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年瘩扼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垃僚。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡集绰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谆棺,到底是詐尸還是另有隱情栽燕,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布改淑,位于F島的核電站碍岔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朵夏。R本人自食惡果不足惜蔼啦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侍郭。 院中可真熱鬧询吴,春花似錦、人聲如沸亮元。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爆捞。三九已至,卻和暖如春勾拉,著一層夾襖步出監(jiān)牢的瞬間煮甥,已是汗流浹背盗温。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留成肘,地道東北人卖局。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像双霍,于是被迫代替她去往敵國(guó)和親砚偶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354