|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。
3 v& C3 j1 J# ^' M. W' C0 Iudp 网络编程只需要使用一个类 QUdpSocket。
& ^0 k5 W& v. A2 `+ H2 Y: u$ @" R# n
* {8 o5 y0 N2 {# |4 D
本实验中对 QUdpSocket 的基本使用:1 m& d+ F. ]' W, e0 ]+ ^
1.创建 QUdpSocket 对象。: a7 l' T7 `: V" L
2.绑定端口号8 D+ J9 X1 b6 Z0 F
3.数据到来触发 readyRead()信号。
6 x( |' m3 p/ s6 `' u+ i$ i9 }) @4.读取发送数据。# m* I. `0 w. ?( C5 n" x. ^
5.关闭。) O6 D, y& p- m: O" B9 [
具体步骤:
7 p/ _% w7 [/ ?# I" A步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。: I! x- e8 L: M7 e5 a( F) m6 b9 z
. H' k) E8 Z+ `/ E5 Q$ r
步骤二:编写代码
5 i& B: \0 ^- n7 V0 }% ]1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号
* k7 A1 M5 x. _/ ~: T8 c+ ?(),在绑定的槽函数内去读取数据。4 i! j% q Q& e ?( \9 Y5 d
2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取6 i6 f0 `4 _) E, v. g
完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。, V+ [4 B+ a( Q; Y, ~, _
readDatagram(data,size);
/ ~8 m0 c0 c6 f0 s9 M* F9 I; B参数 data 为读取的数据,size 为数据长度。, Q$ w( R- \' [1 F; W W8 _* z6 |
3.发送数据,使用 writeDatagram 函数,2 s: b4 a+ l5 U8 y# ~
writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);
: F5 ~: K4 B# m8 n; QData:发送的数据。# f" D* U3 G; a# ~* l3 a
Len:发送的数据长度。
+ W; G. X; s5 PHost:目标 IP 地址。
1 p) v( M [# D7 L3 ]5 Y% ~Port:目标端口号。3 n: c! k, h2 l" M
4.关闭 socket 套接字。) _; g F; K- G6 @
代码如下:6 ?+ X- v- f# q3 ?
- udp.h, c4 l- B! C) Q& C& N. R. E; S
- #include <QMainWindow>
4 t, i c: ^; S - #include <QUdpSocket>5 s0 x T5 A8 R
- namespace Ui {; c4 ^* s( S4 \2 A. F. P; l
- class Udp;+ M# s* {: k- d5 E9 p3 G: O
- }$ C8 x7 u3 u1 b/ k. k
- class Udp : public QMainWindow* q) r. S( q! n/ J
- {
]/ a7 e7 A# Q3 x T, b - Q_OBJECT4 n& U1 y& m$ B) Y3 k
- public:
. p0 i' H9 ?; f( w# Y" o' ^ - explicit Udp(QWidget *parent = 0); ~Udp();/ e. T' I+ i/ f5 @6 J1 [) L
- QUdpSocket * udpSocket; L4 S' \9 j1 S: n P: f
- private slots:+ G( q: |% h2 F% |8 V3 s2 C
- void on_pushButton_clicked();
2 ^& x# p( [1 Z/ k) T6 p. G! l9 O - void readyRead_Slot(void);1 @6 V* F) T- y: K H
- void on_pushButton_3_clicked();
$ s, ^$ u& p2 R% }" x! Y( u - void on_pushButton_2_clicked();, v' p Z3 u# o
- private:& d) @: ?. H% m/ ~ n
- Ui::Udp *ui;
$ p n: ]" c! H" v: t; V - };
8 p0 o" W( z( _$ s' U- I+ N - udp.cpp:. P) B7 W/ u& v9 s/ i# m" n
- Udp::Udp(QWidget *parent) :" l* K! k0 w4 i& \* I ^8 T9 e) r$ L# C
- QMainWindow(parent), ui(new Ui::Udp)
}, i$ b) P& {( l6 {- N - {
c& [. M _3 C - ui->setupUi(this);) m$ U, Q; A1 O; _& N5 B4 s
- udpSocket = new QUdpSocket(this);2 @; i Q1 A; l: n0 r4 [
- }
* h4 q2 ~$ J+ _ a1 C - Udp::~Udp()
( a1 ]" ?! u: X5 }0 a2 ]& s. z - {2 ?/ Y( f1 N& X# X5 b
- delete ui;. k7 T1 X% S7 ^* X2 `
- }8 R: z; R) ~4 P ~8 @
- /*
# x S$ O* l5 b0 o" u - * 打开按钮0 e$ W$ w" p% T9 `( l
- */7 U6 n9 L9 z+ ~$ j
- void Udp::on_pushButton_clicked()8 m3 P3 X! D% _$ y, P
- {5 a5 z K; V5 i# q
- //绑定本端口的端口号/ s! E. \# w' k: W
- if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){
2 N, I( ^+ l) y n2 q. h/ r - QMessageBox::information(this,"提示","成功");
; H& C9 h* _7 P" m - }else{
/ T$ A1 ~0 D2 s5 ^- u3 y/ d4 P" k - QMessageBox::information(this,"提示","失败");
$ N; d8 o6 m* |7 x - }
" F I7 E, k& Z6 q+ [* R* i4 Q - //绑定数据信号和槽函数" X. a f- X* ~- O* o& b
- connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));1 j* D& y1 {1 g) b1 {2 @
- }
: d$ x" N# L3 i: | - /*
: b2 L! b: @) ]6 K - *读取数据槽函数
: @# E, Z2 ]" F) H t - */; Z+ h+ g2 F: q& E5 S6 e# m
- void Udp::readyRead_Slot()
) m- B3 B' S- z! z9 ` }. P - {
4 a3 z4 P$ G. X - QString buf;7 ^2 K% d/ m& f6 j3 h( z7 j
- QByteArray array;/ \: y) p6 u# V ^3 s
- //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取2 ^, P& m& X. O0 P, ], V: r
- while(udpSocket->hasPendingDatagrams()){
9 J, i9 k9 F1 [* _. i. M# \ - //获取数据
9 i( ^. _! Q& ^7 a) K: ~: | - array.resize(udpSocket->pendingDatagramSize());" a4 N% |4 f" { }0 P
- udpSocket->readDatagram(array.data(),array.size());' B2 _2 s6 A& H4 U) p
- buf = array.data();* @1 ~2 Z/ L3 o! I* S6 B0 R
- ui->recvEdit->appendPlainText(buf);
+ M3 j" i$ {# E# E! ?' D - }1 z* ^& W6 O$ L! d- U8 H6 F
- }: q: T5 R2 h' M. ~" x, T% q% L
- /*7 q+ Z3 O- z; @
- * 发送数据' W+ r0 `6 z: j# E5 X8 m* q+ L" ]
- */0 r1 m! N, h, O6 W: K
- void Udp::on_pushButton_3_clicked()
& z5 a3 L; A1 a. O - {6 B i- Z" l$ a0 | O2 D( [
- quint16 port;
" g& m* F4 n7 b, e, } - QString sendBuff;: y' q7 W! ]. c5 ~
- QHostAddress address;$ a& g. ^4 U( R) r% @3 `1 I; A: f3 p
- address.setAddress(ui->ipEdit->text());//目标机地址! ?- g l/ P( y1 m+ O0 e, H. J8 y
- port = ui->portEdit->text().toInt();//目标机端口号
# g4 ~: z) l0 _6 z' w* d - sendBuff = ui->sendEdit->text();//发送的数据
+ ^! p% B% @+ k/ s L - //发送
3 n% o9 ^1 V: K9 q - udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);% p# Z# J7 Z' U; ]/ _
- }
6 Q2 d- u: y/ R4 i7 V( m - /*
+ r8 N# k* v6 C% I& L - *关闭) m* ^* Y, ]+ y. B8 J$ ]9 x
- */
6 s/ W* B7 e6 S1 k: H+ I% Y* A - void Udp::on_pushButton_2_clicked()
! Y2 H6 s _# t/ |' x' \ - {
$ D1 R, r& c8 R* Y* } - udpSocket->close();- i6 \ _! P H
- }
复制代码
) z4 E$ p# A! G/ x% z! L3 @% p3 e) S$ z$ X8 V, R% x' K
|
|