|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。
( o0 n& b6 }; {+ E+ tudp 网络编程只需要使用一个类 QUdpSocket。7 U2 c- y4 p; I2 |
2 y3 t! e$ n( q7 p8 b* ~. P
本实验中对 QUdpSocket 的基本使用:- @( Y: D8 Z: @4 Q" S N7 a+ g
1.创建 QUdpSocket 对象。
1 `: F1 J4 U' L7 E+ h2.绑定端口号8 h7 Q7 O3 ?5 F6 `: W
3.数据到来触发 readyRead()信号。
2 t V0 c8 M, o, g9 H8 d9 H4.读取发送数据。$ _/ c! Q! C9 Q
5.关闭。
- B0 s& F0 d' E+ L" _- ]具体步骤:
, N' Y! Q% j6 D# A0 o步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。
& ]) ~$ C7 S( F3 \, o# T
( X0 x( m" x! R1 {7 K步骤二:编写代码# S" V6 {! f' d, Z7 q! D
1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号
" W; u0 a! i( L9 {(),在绑定的槽函数内去读取数据。+ D# o5 l Y0 G
2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取
9 N9 q, [; R4 B7 F3 |完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。
( R/ J2 \8 M. |+ v4 p* Y& |9 xreadDatagram(data,size);
8 h( ^- h: c" B; I参数 data 为读取的数据,size 为数据长度。
! V+ I9 i' o1 I* {' _& j/ K6 }1 f3.发送数据,使用 writeDatagram 函数,
$ j, u4 o, J$ a7 H+ [/ fwriteDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);. ?/ P* e5 {1 v/ R5 v3 l+ J
Data:发送的数据。4 w/ h" {8 l8 K" d) p
Len:发送的数据长度。
" E& ~6 v$ k$ z6 |Host:目标 IP 地址。" B( n; i5 F, f8 {% M4 c
Port:目标端口号。9 Z: n& W" ~& g) q# ]
4.关闭 socket 套接字。9 ^( K! o, g2 u0 a8 u6 Q: Y
代码如下:
1 ~2 l, J$ T) O; p- udp.h4 P! d( d1 d; j1 P6 ^8 Y% i1 Q
- #include <QMainWindow>6 U$ t; t4 J# e# C! M: O, _
- #include <QUdpSocket>4 D+ Z) y8 ?5 m3 i. s4 v5 S
- namespace Ui { b5 _* c$ |! G4 m7 L
- class Udp;
% `7 o5 T5 X& B# ~% }# a - }
5 y) z6 U, I3 Q - class Udp : public QMainWindow
& p7 b0 @, ~- V" x( U6 d - {
# V4 c q/ m7 G; b/ ] - Q_OBJECT# P; _/ }/ ?0 l: N" A7 t
- public:" c4 l0 b# `5 y/ r' P; [- f
- explicit Udp(QWidget *parent = 0); ~Udp();, y0 X$ t$ e' n' ^4 K- D
- QUdpSocket * udpSocket;* s3 o+ y) l- o7 i. Q1 `: L4 d
- private slots:8 f6 K. t. G: I9 e5 D
- void on_pushButton_clicked();3 m$ c6 a) P$ k: ]) a
- void readyRead_Slot(void);; d! C; T# O4 q/ i/ Y' A0 I; L; I
- void on_pushButton_3_clicked();
0 h0 E, P& y$ u( M+ z* C6 J4 M2 o: v/ G - void on_pushButton_2_clicked();
6 z+ w4 y/ v3 a/ I# H2 C - private:9 L' k, B: [6 k, ?4 H) H
- Ui::Udp *ui;: Z1 A! d4 l3 N
- };
2 V* G/ d# c( X& }: t - udp.cpp:2 i+ @6 j& E* X3 [5 g: _8 l
- Udp::Udp(QWidget *parent) :# x2 C: E* [/ }
- QMainWindow(parent), ui(new Ui::Udp)
; L% L4 ?) A! Q0 `2 X, Y - {; U$ H( o" y8 S" m- h6 D% V
- ui->setupUi(this);* G, `3 @/ L( S
- udpSocket = new QUdpSocket(this);
, j: ^1 q1 T$ W3 V: W - }
% K; r% S4 p" l0 M0 z, O - Udp::~Udp()
) ]! X$ p y; N; w - {+ a1 k$ a+ s3 w' y4 n: q
- delete ui;' }1 q" s4 E( [" g, T
- }9 C% ~' y- C+ M
- /*
& I( J4 k a5 t% n- ]- ] - * 打开按钮! \9 O" u8 s' w E' e5 O D( y- \
- */
) H2 h4 C. T w) H8 ]2 p. ~7 O - void Udp::on_pushButton_clicked()) [1 m( A+ C8 a& U9 p7 l6 x
- {
2 ~: y0 F/ g+ u) e/ V, C - //绑定本端口的端口号- c I. w) g" q, m0 y
- if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){% |0 n9 K# l% f( \+ K( u, _
- QMessageBox::information(this,"提示","成功");! h$ U7 Y5 Q- W; _
- }else{# J% {* M! n4 K& W" k* d9 W! e
- QMessageBox::information(this,"提示","失败");2 E5 I4 h2 F0 j
- }
0 m$ z4 r; W- t f# I4 b1 L - //绑定数据信号和槽函数
. K# L" u2 R. _$ ~1 z - connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));; f5 O: Q% j- C0 P, |9 g1 C) k
- }" Y9 C) f: L* m0 ?$ z: {+ @2 ]+ x
- /*
5 s2 D, N" f s - *读取数据槽函数
4 c0 P1 F9 c* \' L8 q5 F - */4 u, J9 w9 r% b# j
- void Udp::readyRead_Slot(); E# @2 w+ Y8 o7 z" W& P& C6 h
- {3 t6 ]4 C+ L6 U: t
- QString buf;
/ ~8 ^# s* _5 m! W) M- }( y/ u6 b - QByteArray array;
/ t3 D; j/ j$ k7 }) ?8 y- T- h - //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
$ j1 x5 V E4 S; i6 }7 [8 n; [ - while(udpSocket->hasPendingDatagrams()){9 y# W- d1 f6 H, ~0 `, C3 G! f
- //获取数据$ ]& R0 u4 ^1 t! i
- array.resize(udpSocket->pendingDatagramSize());
* u8 [) a+ T. Q) \# a- C2 v - udpSocket->readDatagram(array.data(),array.size());
& [( o" U# V9 t( b0 w9 \ A - buf = array.data();
5 j: j3 L1 S6 e" G' y- ? - ui->recvEdit->appendPlainText(buf);
! J& M3 U7 L8 h4 h9 S, O$ p - }
. p3 P! B0 G: H& h t+ v - }/ s, x2 r& n% ]$ Z$ M4 X
- /*, L' G* e" V% B0 q
- * 发送数据- J4 ?. P. c8 P# }) p% h1 n
- */
- L1 E2 B- Z2 ~- b I - void Udp::on_pushButton_3_clicked()
) F9 }4 `% l6 f9 R( p; o - {7 w/ e6 k2 c+ _: S, b% k" p
- quint16 port;
) F! F8 b( S' d/ j - QString sendBuff;' y* @* p1 ^ Z# C/ |
- QHostAddress address;2 {3 T$ b; O' `4 j0 L
- address.setAddress(ui->ipEdit->text());//目标机地址$ f. ~5 a3 p- T
- port = ui->portEdit->text().toInt();//目标机端口号
! n2 y7 d2 H* Q9 \& F6 I1 a- X - sendBuff = ui->sendEdit->text();//发送的数据
( Q6 a9 @9 g: e. e: n7 P - //发送
+ T7 ^/ P! x% k - udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);
5 l6 ]- a( @) s6 s2 @8 n9 \: g - }
X! `$ }7 p5 J# Y8 O2 T v# D - /*
2 w* v, h8 G g7 G: G/ R# Q - *关闭
- v4 f% W. B2 ?3 O1 C+ `4 ` - */
' z# C3 S0 _# W. e+ c) q& q- X - void Udp::on_pushButton_2_clicked()
2 u/ ?" l) A% | n: }3 |* \ - {
' q: Q0 D9 P2 X) q9 ^8 {; V - udpSocket->close();
; ^5 w3 L8 K r# ^- y" e& v; ~+ A - }
复制代码
% X" A, p) `7 h5 C
2 S' @8 g3 `. T7 R' i
|
|