|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。9 N$ }+ O7 H4 ?7 q; d' q
udp 网络编程只需要使用一个类 QUdpSocket。- ^* |. E1 R0 ?6 @
5 p/ L! q9 X& s2 u$ Q8 W3 e4 {! k" K
本实验中对 QUdpSocket 的基本使用:
}) B! T& u: Z$ A9 l+ {1.创建 QUdpSocket 对象。$ u$ i( L" p4 w5 ?* t
2.绑定端口号$ g4 G* m1 o9 U+ \, v f3 o
3.数据到来触发 readyRead()信号。
& J$ W- K1 k& x/ } T4.读取发送数据。
4 `; U2 @$ V5 n5 d1 O8 `5.关闭。
" B/ T1 I8 a; U5 j/ G具体步骤:
$ x- x# {$ h* q+ p步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。
; `8 A+ a0 N/ m& U# t8 I8 t+ Q
( |; x3 S3 ]+ k/ x- h
步骤二:编写代码
P- J! o3 }& l* x$ S6 Y+ |1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号
0 h5 n% v. @& j! N/ X% R( |(),在绑定的槽函数内去读取数据。4 c; {. P T3 D* m' d! c
2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取# z0 E/ ?+ D* t2 } P2 {" b
完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。) Y1 r, c5 V% c2 F) C& J- v
readDatagram(data,size);* V7 _ }, q5 F# @1 a9 b- ?$ b
参数 data 为读取的数据,size 为数据长度。' R2 j( f0 x7 ^) b& y. P5 \
3.发送数据,使用 writeDatagram 函数,8 b- k' s. s7 B1 h' T$ N) ]
writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);5 U% M( ]& N$ U, U
Data:发送的数据。* w2 \0 ]4 k; L$ r
Len:发送的数据长度。% \4 _5 D0 O/ O: T& G
Host:目标 IP 地址。 ^8 k2 j Q+ ^8 Z
Port:目标端口号。
" i$ \5 h( I# A% c- d- _1 E" k4.关闭 socket 套接字。
; k* O' b: {# z& W代码如下:
9 r4 H& R8 g) u; M& t o' a- udp.h
v/ w1 D1 W R( s7 K7 W- h9 ] - #include <QMainWindow>* y! v9 i2 P( h5 U; b8 e
- #include <QUdpSocket>
, S/ M* t1 K. b+ V - namespace Ui {5 i- |9 n1 j# O9 q
- class Udp;
" W% r8 M. K# J7 S - }
$ B# N' f( L0 e& _4 j - class Udp : public QMainWindow# \& R% J1 i1 _+ P
- {; d$ y7 ~' N K3 F0 l8 Q# d0 v9 m2 T
- Q_OBJECT' L. y2 {' W; {" R$ K+ C
- public:
0 Q9 ?! a, A! J% c - explicit Udp(QWidget *parent = 0); ~Udp();2 f5 F" n6 C% e I+ F
- QUdpSocket * udpSocket;: Z# g6 j8 ?2 m# m
- private slots:' n8 O! K+ k( f; {; F
- void on_pushButton_clicked();
5 ]6 T. o) {2 {# y+ p7 |3 r( t - void readyRead_Slot(void);# X" c% s' ~" G- b& }! l, {
- void on_pushButton_3_clicked();
1 e' o) a8 N; [- j - void on_pushButton_2_clicked();0 `/ l7 z0 b/ U$ `( t
- private:
, w0 w# }$ U! G1 X7 R. m - Ui::Udp *ui;
1 p, p. R9 \& R1 D+ H - };4 [% t: W) d7 \3 z+ P* l$ V5 x
- udp.cpp:% @4 j. ~! d6 L$ v
- Udp::Udp(QWidget *parent) :
6 U0 o5 n9 `7 Z - QMainWindow(parent), ui(new Ui::Udp)3 a7 P, V/ b, P6 J* K1 k
- {6 x( x0 ^9 B) ~4 s8 _4 d/ v8 |
- ui->setupUi(this);
! L+ j8 I, C6 n - udpSocket = new QUdpSocket(this);
4 E9 c9 d6 C& l' s. X, ?' q - }
2 r% C( X. n2 m7 j9 v. V - Udp::~Udp()8 ^0 \: H2 q! M3 s7 X2 R* p
- {: ~1 Q! A& n! o8 |; X, l7 Y
- delete ui;
% S1 i6 r2 K% a4 D( M - }% p! ` o6 V$ A
- /*" A: m1 A" [( R# F5 X! e- M
- * 打开按钮0 S* D" C" e1 X5 F4 i$ Z' {
- */) H& j+ `6 v7 }+ A& G- A3 b- a
- void Udp::on_pushButton_clicked()' L/ P$ f/ T! j% \
- {
, {8 j2 y: A6 q2 Y - //绑定本端口的端口号
: n; ~& ]* |/ g - if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){
6 ^# h. f6 [: F3 S2 h% }9 A" W - QMessageBox::information(this,"提示","成功");2 i3 f, G7 x1 C! ~4 r% ~
- }else{7 q+ @8 V# }( n5 q3 B) \7 E
- QMessageBox::information(this,"提示","失败");$ @8 U- ~7 m& E4 C# V) Z, o
- }2 q" Z# H0 s/ K# ~5 H4 H! H/ }
- //绑定数据信号和槽函数
0 O7 J/ ~ G) q" v1 P: s8 N - connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));' S# |9 n2 q" ^- A- L
- }
6 A% k7 L0 @: ^& t! a) x - /*
6 Z% X# @# P0 l, m - *读取数据槽函数
1 } N& v' U' y9 q k - */- c( K( H( D& N- f0 O! n
- void Udp::readyRead_Slot()
; T! C3 [5 J7 t# j4 W - {& |- Q$ E6 z8 l
- QString buf;
o) g+ l0 n- u4 m6 O9 l) A/ e - QByteArray array;# k+ s. K: L2 P) |
- //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
2 R6 ] G! i4 S - while(udpSocket->hasPendingDatagrams()){
* `0 P7 |2 [$ U: t0 h" T1 R" L( v - //获取数据+ E6 n$ V* \5 _% f7 J
- array.resize(udpSocket->pendingDatagramSize());8 n% q. x" h0 k9 H6 D+ Z' _
- udpSocket->readDatagram(array.data(),array.size());
: @/ m$ ^' \2 P1 `/ x) Q! j - buf = array.data();7 J1 |- W/ F9 s6 X
- ui->recvEdit->appendPlainText(buf);
9 e1 y3 C* l Z; b& E( S1 M - }! S5 y/ w0 \8 H2 u" P, W& {
- }7 N& z5 M: H3 Y1 Q& t T# O
- /*% t' B2 V) P1 Q0 @" o6 ?
- * 发送数据1 M! Q( K& W9 V9 t1 g9 T
- */$ e3 Q k3 S5 D6 M( m% S5 s4 a) ?
- void Udp::on_pushButton_3_clicked()
0 O, v! B! D* v8 L6 Q - {9 T0 e T ~/ \! e. q c0 j
- quint16 port;
+ c2 g$ q" t4 D" w M; o/ ]) L# w - QString sendBuff;
$ j U* }! l1 `1 Q; r; g - QHostAddress address;; d$ s$ F& l1 Y8 L N
- address.setAddress(ui->ipEdit->text());//目标机地址1 f3 @. \) N& Q4 i
- port = ui->portEdit->text().toInt();//目标机端口号3 @' I. @7 k2 c2 I+ E2 u, J$ G- V
- sendBuff = ui->sendEdit->text();//发送的数据
5 p5 H M0 s ^% {" Y* f0 P - //发送1 t1 f$ y5 U% s5 ~- f
- udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);
5 l- f: n+ q! n - }
2 u- y1 ^ i4 i - /*; l3 Q! L3 a0 W4 [6 b, y
- *关闭0 H- ~* H# N+ T7 \: N% e1 M
- */: {9 r+ {! h7 o5 P7 f: n6 D
- void Udp::on_pushButton_2_clicked()2 I& `3 o+ {# C) F7 T/ V D
- {8 |5 g, L# x7 F" H0 `# ^0 U" _
- udpSocket->close();
u$ L& z0 L5 ? - }
复制代码
% x! `3 z2 w9 W+ b0 C
8 W; r* W$ n5 Q/ P# X4 J% K |
|