1.什么是UDP?
以下解释来自百度百科:https://baike.baidu.com/item/UDP
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。
UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
2.新建一个工程
-
Projects
->New Project
->Application
->Qt Widgets Application
->Choose
,见Fig2.1。 - set
Name
toUDP
,蓝后一路Next
直到Finish
,见Fig2.2。 - 工程结构中各个文件夹放的东西:
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
,进入界面设计,见图Fig3.1。 - 在
Display Widgets
中拖两个Label
过来,并依次双击将内容更改为对方的IP
、对方的端口
,见图Fig3.2。 - 继续在
Input Widgets
拉两个Line Edit
和Text Edit
一个过来,在Buttons
中拖两个Push Button
,并按Fig3.3中调整布局和在右侧属性栏中更改各个控件的名字。
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
,整个文件如下:
#-------------------------------------------------
#
# 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
-
点下Fig4.1左下角的榔头,编译不运行一下。
Fig4.1 Click Biuld Project
5.编辑mainwindow.h头文件
- 内容如下
#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(); // 槽函数,处理信息
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);
// 分配空间,指定父对象
udpSocket = new QUdpSocket(this);
// 绑定
udpSocket->bind(8888);
// 获取本机ip
QString strIpAddress = QHostAddress(QHostAddress::LocalHost).toString();
// 设置窗口的标题
QString title = QString("服务器IP:%1,端口为:8888").arg(strIpAddress);
setWindowTitle(title);
// 当对方成功发送数据时
// 自动触发 readyRead()
connect(udpSocket, &QUdpSocket::readyRead, this, &MainWindow::dealMsg);
}
// 信息处理函数
void MainWindow::dealMsg()
{
char buf[512] = {0};
QHostAddress clientAddr;
quint16 port;
// 读取对方发送的内容
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);
// 设置显示内容
ui->textEdit_Msg->setText(str);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
7.0给PushButton_Send增加点击响应事件
- 在
mainwindow.ui
中对send
右击选择Go to slot
->clicked()
,见图Fig7.1和Fig7.2 - 自动跳转到
mainwindow.cpp
- 新增一个响应单击事件的槽函数如下:
void MainWindow::on_pushButton_Send_clicked()
{
// 获取接受方IP
QString ip = ui->lineEdit_IP->text();
qint16 port = ui->lineEdit_Port->text().toInt();
// 获取编辑区内容
QString str = ui->textEdit_Msg->toPlainText();
// 给指定IP发送数据
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);
// 分配空间,指定父对象
udpSocket = new QUdpSocket(this);
// 绑定
udpSocket->bind(8888);
// 获取本机ip
QString strIpAddress = QHostAddress(QHostAddress::LocalHost).toString();
// 设置窗口的标题
QString title = QString("服务器IP:%1,端口为:8888").arg(strIpAddress);
setWindowTitle(title);
// 当对方成功发送数据时
// 自动触发 readyRead()
connect(udpSocket, &QUdpSocket::readyRead, this, &MainWindow::dealMsg);
}
// 信息处理函数
void MainWindow::dealMsg()
{
char buf[512] = {0};
QHostAddress clientAddr;
quint16 port;
// 读取对方发送的内容
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);
// 设置显示内容
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();
// 获取编辑区内容
QString str = ui->textEdit_Msg->toPlainText();
// 给指定IP发送数据
udpSocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
}
8.0测试
- 保存一下所有文件
-
<F5>
运行,见图Fig8.1 - 在IP和端口中填入本机的也是可以收到的或者你再开一台电脑一起测试,我是直接填本机的,见图Fig8.2
- 点击
<Send>
后,如图Fig8.3,证明发送成功
Fig8.1 运行效果
Fig8.2 填入参数和数据
Fig8.3 发送成功