|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。- y7 W; @9 \6 y* D
udp 网络编程只需要使用一个类 QUdpSocket。, Z: E/ f* H6 L
% R, G/ l0 s2 E! n8 f+ c* `/ V5 _
本实验中对 QUdpSocket 的基本使用:* L- I0 U7 z1 |
1.创建 QUdpSocket 对象。
) u1 s- y ?* F5 L- i2.绑定端口号- n! y$ S. z @8 k
3.数据到来触发 readyRead()信号。
0 [( u& b' b f e# P% [" ?! I) U4.读取发送数据。6 B6 t5 C, f" I& h8 ]: q
5.关闭。
* h( u, S0 Q& R/ f" f, v) Y. }具体步骤:
+ _. p, B; P) G" ?步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。
" U& |3 H( h2 M0 v8 T
; `" s, S' }: I4 o步骤二:编写代码
% A! F' o* L8 C \ Z; ?7 U1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号 y; }9 C2 u3 Y1 I
(),在绑定的槽函数内去读取数据。
6 e W3 Z; ]+ |3 f2 k5 Q- e2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取
! e# g: V1 J V. S) @" C" d1 ^完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。3 [8 r9 U( _$ L
readDatagram(data,size);
7 }5 ~1 {' x6 B. K* F参数 data 为读取的数据,size 为数据长度。
; f) J0 Q/ X; a/ J3.发送数据,使用 writeDatagram 函数,
0 ] W. r; K( N) h" \# mwriteDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);3 a0 T, o( f, C# z7 k/ z5 }6 a
Data:发送的数据。
4 w. L$ x7 e. p/ S- C) i- WLen:发送的数据长度。( E# W5 i; \! I' j0 q
Host:目标 IP 地址。
* Q9 U0 a( j p- \' v) l( [+ sPort:目标端口号。
U8 R% I/ V+ U# e5 R* r4.关闭 socket 套接字。$ o' r: H) u" u. {3 z, \
代码如下:
: f+ p, p- ^9 V- udp.h
" T& {) r) H4 P - #include <QMainWindow>: m1 }9 L- o2 Y5 [( f' o% d
- #include <QUdpSocket>
# [6 B# D3 _- {# d# C2 k) E4 M - namespace Ui {8 \ J, Q# q6 n5 F2 ?- s) A
- class Udp;
6 U2 L. z7 I4 k! P/ P& @ - }- Z. }' ?. N+ M
- class Udp : public QMainWindow' i* C/ `, j" n* T" {7 k p
- {
0 K4 ^8 e( l8 s" P+ d+ q# Q - Q_OBJECT
8 |& H" T3 g2 v. q3 l. ^ - public:3 b2 |6 y; u, w+ ]
- explicit Udp(QWidget *parent = 0); ~Udp();
8 c* `) o9 r1 P - QUdpSocket * udpSocket;2 J* I! a4 g+ }3 v9 w; q
- private slots:
" `6 u* M* ?* ~$ ~% J - void on_pushButton_clicked();6 o# ^- D" n( O8 w3 h, s
- void readyRead_Slot(void); K: F1 R# |% [2 m0 ?5 F7 D
- void on_pushButton_3_clicked();; ]( B- c# V, x6 I9 [) e
- void on_pushButton_2_clicked();) U/ h: s- I$ y' @, Q
- private:
- \0 }- N, x0 Q& x - Ui::Udp *ui;' o4 m+ ^' Y5 ^5 Y+ D: ?$ @; @
- };/ P. F2 x+ ?; t: e
- udp.cpp:
" x ]- x+ [. _, m9 |3 b - Udp::Udp(QWidget *parent) :. H6 p8 q: T) U- J/ P* i" h4 i
- QMainWindow(parent), ui(new Ui::Udp)3 R( G( h9 t; ^% I8 L3 j. }6 y& c
- {
3 U% k5 e" n2 P" Y - ui->setupUi(this);
7 m! j; M0 h! a4 u( F6 u - udpSocket = new QUdpSocket(this);
2 G" q4 ^2 h6 l4 S- Z+ _0 F& E" M - }9 ]0 M8 W: _# i+ F- B( S! o. N, [
- Udp::~Udp()
4 S# x' v6 \: R - {
8 v4 ]( {. T9 P5 ~ - delete ui;" c) ^ }+ ]3 J4 ~( y; V# L) m
- }
6 ?0 [4 m) f3 E" ? [ - /*' a! ]2 i* H+ Q! i1 ?8 ~
- * 打开按钮
( c. N. W5 `" q; p - */
/ e3 G8 K$ M, ^' F8 ?% [$ A8 H5 \ - void Udp::on_pushButton_clicked()9 S" ?# M8 l/ Y/ A/ i4 C
- {' `" Q7 C8 z: q: s
- //绑定本端口的端口号
8 V6 J. w, T* Z6 j8 |% o - if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){
8 \8 E1 M4 a1 m - QMessageBox::information(this,"提示","成功");
4 B* Q- R$ Z Y. i - }else{
4 @ @- V, |9 x$ E; y - QMessageBox::information(this,"提示","失败");6 w) `, H( H- O9 [' v* m6 C. u/ ~+ p
- }1 C# T" p I$ _, K% z$ N
- //绑定数据信号和槽函数$ p, f2 g3 H5 R4 }1 ]
- connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));
+ k7 K6 p& v* z4 F& f/ T - }0 L" ?2 p% ^% ]+ f3 F
- /*( A6 n: F/ A* R+ K/ }! K- e
- *读取数据槽函数
+ e# Y1 f! o. F& f - */
" j" Q/ R5 o- h; |5 K - void Udp::readyRead_Slot()
+ ?6 T; p: I" C) N4 H0 ]9 u - {( P. n2 u2 _5 |- v9 d/ C
- QString buf;
+ K' E [; ^1 C6 V0 i! {% I" @ - QByteArray array;5 u$ z0 Y: d; q* c
- //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
( _- k0 V8 c8 x) x& u `! o% U4 i- E - while(udpSocket->hasPendingDatagrams()){
( f$ j! U$ c+ G( I5 Z& e# D - //获取数据
* P) v5 g; P$ c: i; T. x - array.resize(udpSocket->pendingDatagramSize());( h( I( }+ `5 E9 u% I, w: q5 a- V
- udpSocket->readDatagram(array.data(),array.size());; \* @" Z" j6 C: z- i' _
- buf = array.data();! ~# y1 ~4 N( @; h0 U" y
- ui->recvEdit->appendPlainText(buf);' b9 D' P6 u4 W4 {! w4 I; A$ ?$ _
- }- H9 I/ ]+ @/ Q; a0 B8 B% y- ~
- }4 d5 e/ j3 B- c; A1 l9 V- w
- /*
2 v$ K* R% F! } - * 发送数据$ Y3 R8 @' Q0 J7 r; T4 ?; b
- */; V0 B6 I" t5 _2 M2 K' p
- void Udp::on_pushButton_3_clicked()
' B; ]8 T! n) J. U+ j3 L - {
3 U2 Y! U) [8 [ - quint16 port;
8 U: z) X: |3 B" g; W; B - QString sendBuff;
& j' s/ T; z! r) i! U1 ? - QHostAddress address;
( h) s! k1 R0 D% |$ O. P) ~+ C - address.setAddress(ui->ipEdit->text());//目标机地址5 X4 s& ~3 w( q8 K
- port = ui->portEdit->text().toInt();//目标机端口号
4 z3 g0 p X9 I* Z+ } - sendBuff = ui->sendEdit->text();//发送的数据
1 I# P2 N0 Y6 i - //发送9 j& G! V" w4 y5 Z) A: @
- udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);$ B" U2 Q7 }( ~+ Y2 {: i
- }' P+ q; L1 _9 f4 h
- /*
. D6 c2 D5 D6 E& I9 _! V' Z( o2 }, b G - *关闭$ w- p5 r2 g- F7 P$ q$ w
- */+ S2 E. E7 `$ S& B4 J
- void Udp::on_pushButton_2_clicked()' t* K0 x( f4 d. i+ ^7 I
- {
# n/ L3 [& t& N, k - udpSocket->close();; s) i# J, U0 Q; S# K& I% y9 |; ^
- }
复制代码
+ Q2 @/ z: W7 J5 k5 k( b
3 S- h. n a x {9 I9 \0 H! Z0 x" O |
|