|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。* m& O7 W3 I& c: y/ v6 l
udp 网络编程只需要使用一个类 QUdpSocket。* _4 V# y: R; x
3 R9 z+ r" a$ i- q8 e% `
本实验中对 QUdpSocket 的基本使用:- E6 q; R3 x) r: o, l2 X6 v
1.创建 QUdpSocket 对象。
0 C7 c) J$ F% Y: r2.绑定端口号3 X9 l; y4 |& T6 [* s
3.数据到来触发 readyRead()信号。
9 r; ^& @+ X9 {- F& p; ~; g& a0 U4.读取发送数据。
6 q$ B, C( f, h7 V7 t% p5.关闭。; W9 Y- ]0 D; C7 |0 v
具体步骤:0 c9 I" n$ g3 i1 N. f# {; J7 l- M
步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。" q8 M4 A7 ^& W/ f% o
5 t( p+ O/ p$ Q' h
步骤二:编写代码
. u1 z: ?, t' {: r- T v1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号
8 d% z( c2 e5 m6 j8 V(),在绑定的槽函数内去读取数据。4 W( {; a) d. A$ U1 [: o
2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取& \& U' Q) Y; u0 o! Z8 W$ R! m1 [
完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。
2 J- D. Z M N' t3 Y7 wreadDatagram(data,size);& x) v Z( S/ s
参数 data 为读取的数据,size 为数据长度。
# l0 Z5 M) g- q, Z `4 ? Y3.发送数据,使用 writeDatagram 函数,% z; O+ ~9 C* ]: a7 s
writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);% a0 C5 a6 N3 y
Data:发送的数据。
+ O. _6 _. Q( }9 I0 K* ^Len:发送的数据长度。
# u' {0 {+ [/ x* k8 l& KHost:目标 IP 地址。/ z q7 A' e6 Z F4 l ]& y
Port:目标端口号。$ X/ J% j1 h. ^+ X6 D
4.关闭 socket 套接字。' g: P7 d9 X7 l/ w- i
代码如下:
) g: y1 \2 i( c( P2 D6 a' U( s- udp.h
$ J3 i& x% m5 J4 A/ b; U. d - #include <QMainWindow>1 V0 n4 h6 T9 I) O* E0 g0 [
- #include <QUdpSocket>: k$ L/ M$ W: F$ Y
- namespace Ui {" _2 _# Y, g* ^( N6 [: m9 z9 e8 p' R, T
- class Udp;
: G& B- h7 @0 J% ^" u( U4 a - }4 F0 F f( x" P& e' T
- class Udp : public QMainWindow
f4 P* j+ Q$ i; c+ n9 p, D6 V' l - {0 V5 p2 z( K [
- Q_OBJECT9 \8 I/ O" z, p, I8 Y! k. z
- public:
- \# R9 D, I" i* t: X - explicit Udp(QWidget *parent = 0); ~Udp();; Z3 O2 o# u* M# l) n
- QUdpSocket * udpSocket;5 D1 C. q& A! L6 O
- private slots:* W7 n$ [! Q0 ~0 o6 U4 I+ m! b4 |
- void on_pushButton_clicked();
- Z4 b. n( R5 Q - void readyRead_Slot(void);1 T) M( V9 y) d3 U6 u
- void on_pushButton_3_clicked();, U2 @4 l0 h* H5 J) @3 G9 q1 o5 W
- void on_pushButton_2_clicked();& n8 i, J2 u0 @! E
- private:
* Y" s4 i8 {, I: L" n7 Z6 p* b - Ui::Udp *ui;
3 f. {6 N% t: {: f( y6 ^" {3 T - };
0 N( _3 w }4 ~ - udp.cpp:/ j9 t6 ] }& K+ T$ Y e! S
- Udp::Udp(QWidget *parent) :5 b5 L- [6 n& z4 w7 u# E
- QMainWindow(parent), ui(new Ui::Udp)
. \1 z/ U; a0 D( e* z/ [ - {) T8 } s9 \3 L3 U3 `! c
- ui->setupUi(this);4 f9 [. _7 c& U
- udpSocket = new QUdpSocket(this);' [( `, n3 b6 \ O
- }
/ _* k* Y$ y1 V. H$ G% G - Udp::~Udp()
- J% B2 A. Z9 P - {, ]7 x! x( ^- C0 C' @0 h$ V: B
- delete ui;7 J- G( @8 {! T$ g
- }5 a C, B! k3 e9 W- ~: [" j' z
- /*% i L3 P7 g; i
- * 打开按钮 y# w' ]' u8 H
- */
% _3 x, K* c/ k" G# @3 s3 @6 r - void Udp::on_pushButton_clicked()
; G0 [% B2 l/ C/ T% F - {0 g/ k3 x& j% a$ L
- //绑定本端口的端口号
' \7 T1 w9 A+ V4 [! R+ j0 _ - if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){& n$ U# d2 q1 c9 s
- QMessageBox::information(this,"提示","成功");
5 W; R: [0 l6 j) m - }else{
2 i6 K3 Q! s; ? - QMessageBox::information(this,"提示","失败");
% @4 t" ]' _5 ?+ G& n* z) K - }& H& S1 n6 h6 m; a4 Z3 f
- //绑定数据信号和槽函数. M, [' |" {1 f- E6 @* F L
- connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));, {5 |* G8 d: J- t( f" u
- }: l8 I6 d) f& g9 `+ t8 |$ U
- /*) W6 N* J4 h+ C$ s, ?7 ]& {5 P/ _0 X
- *读取数据槽函数/ P, G5 g% P# N/ c- n
- */: e& m9 d" L; C" Y( h
- void Udp::readyRead_Slot()$ E+ ~/ \* j+ W3 P; P( C
- {( b: |/ A2 o6 w/ @$ l0 E$ `
- QString buf;+ E3 S: y% {: m( e g+ ?9 d
- QByteArray array;
' f; I& j4 t$ F% s3 d0 W - //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
! z6 d( k# j6 i: y/ S: c - while(udpSocket->hasPendingDatagrams()){
]$ b& t ?# O. e o9 n - //获取数据, b' Z7 A) U; I4 P
- array.resize(udpSocket->pendingDatagramSize());
0 C( ^: B; L/ e( ^% h - udpSocket->readDatagram(array.data(),array.size());2 |. ^/ q* K( S+ _9 D
- buf = array.data();1 x2 V2 w# E9 F# K4 g6 B( u
- ui->recvEdit->appendPlainText(buf);
0 z$ B) Y, d& H4 i9 @# h - }( e) v) }# H4 t; d) H" p. a1 z5 w
- }
- n5 e5 P; S+ y# b& [, ?7 n - /*
$ J6 W2 z8 g# t - * 发送数据/ ?3 t7 P: P8 u3 b# S x7 s
- */3 o8 W9 }, x5 J, D2 V
- void Udp::on_pushButton_3_clicked()6 y4 j5 U1 x! @& w1 S" }
- {
7 e& C2 }+ l3 u; X - quint16 port;# D" B. @, G% [3 Z' k0 i
- QString sendBuff;
+ [* _" k4 F! ? - QHostAddress address;5 o, f2 }( E$ S3 i
- address.setAddress(ui->ipEdit->text());//目标机地址0 v) X) c+ q$ W; W5 S
- port = ui->portEdit->text().toInt();//目标机端口号
: h* m, ]9 w9 {. r" y6 L, N - sendBuff = ui->sendEdit->text();//发送的数据0 h8 i3 ]+ A d$ H+ s3 P/ n
- //发送
+ A, ^6 x0 p l4 l) C/ `+ y2 v3 i - udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);
9 n6 ~1 I" ^8 D; V. { - }8 A. t; e9 O3 C8 A
- /*+ o! I' O# ~+ l! b( h
- *关闭! v0 j/ h, O% {0 d
- */# j/ \* h; ~+ x# @# T: i& j
- void Udp::on_pushButton_2_clicked()0 K! U+ X! N: \9 H
- {
- x9 j2 _( i4 v9 X - udpSocket->close();
, [" l$ _% @& V ? - }
复制代码
6 T+ q: X0 ^$ l, N: W, X: o
1 j+ V Y l& t. a5 q |
|