|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。
# f' Y+ g5 L# V {0 E. [$ c. Vudp 网络编程只需要使用一个类 QUdpSocket。/ `/ Y. s4 J& r2 n' Z
# c. b% @- Q1 f$ u; M7 D A
本实验中对 QUdpSocket 的基本使用:
( s; O# k7 B) F8 ^1.创建 QUdpSocket 对象。% U. Z$ ? K) O( S1 R5 C
2.绑定端口号
4 T! p y: ?( J" |5 O3.数据到来触发 readyRead()信号。" [ _8 ^, J. B# h) M N; S" w/ w
4.读取发送数据。0 D- P; a# G4 ?& Q; E+ g- u' Y
5.关闭。! E" S+ d; A1 f x: N3 B
具体步骤:
: x6 }3 K! }& U步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。) X# J& V) n5 ^/ o: A7 a
5 A" Y" v- v( `步骤二:编写代码
2 l- s; l- a \% u* J/ i* y) i1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号+ B' T E" j$ K: v. ?" Z
(),在绑定的槽函数内去读取数据。
1 H7 T; j& ?" `2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取
- g# y3 V3 w# Z3 z! L. h完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。
' j4 c+ R% T; ^# ~readDatagram(data,size);
( d* y- Q0 F/ ~5 d( d9 |% n5 k参数 data 为读取的数据,size 为数据长度。
+ j' H( l Z/ z" j+ ]) v6 ~, B- ~3.发送数据,使用 writeDatagram 函数,+ I0 o! R, B, p2 m( W4 r9 k
writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);/ V( @: ?5 W- ~( A$ I8 e
Data:发送的数据。6 |, e. D W I K8 ?
Len:发送的数据长度。
) J: r6 j Z& H' B/ l3 yHost:目标 IP 地址。
; P9 Q; Q! |) ]$ C$ s; {! `Port:目标端口号。; P8 Q" S% l& W* P G: X
4.关闭 socket 套接字。# L* F) u) r1 }4 n& ^
代码如下:/ {/ }( O$ N6 A& r) M& t, b1 K
- udp.h: v. N. B X$ t! ]7 ]: [6 t
- #include <QMainWindow>, a* ^2 a2 `4 p {/ i8 Z% e
- #include <QUdpSocket># G5 a$ C! j' }& X( n
- namespace Ui {
: C Q ], M# {: |& r: w: A0 k - class Udp;
" g7 q( ?1 x7 M d3 z - }
' _# O/ h; G/ |6 q, L; v! u - class Udp : public QMainWindow, r9 d- {6 y4 ^0 {3 h g$ s
- {
, b5 p( N2 u6 @! _4 L - Q_OBJECT
8 j! J" P$ r# `3 O- | - public:
" }/ C& ]; U- P( T - explicit Udp(QWidget *parent = 0); ~Udp();
H4 n# | |* |5 A - QUdpSocket * udpSocket;
3 Q$ L6 j5 l/ C4 c - private slots:
* `/ K! v2 V t# I3 ~3 y - void on_pushButton_clicked();$ }4 {; R, O1 S9 R6 ]8 C; [
- void readyRead_Slot(void);8 B2 T' |5 R" z& N% k) M: D, V
- void on_pushButton_3_clicked();
8 n- h9 b1 O7 T; i. [ - void on_pushButton_2_clicked();. P5 _8 m; c! b0 w2 _; Q- Z+ d0 E
- private:
0 i) C& G" ]3 D5 U% } - Ui::Udp *ui;$ @& o8 O8 B. v1 z# U# }! r8 r
- };& `; V- Y2 b' w/ z" a
- udp.cpp:" d: q, J& V( ^( ]3 q. R
- Udp::Udp(QWidget *parent) :
& d& K( p) ~% P* W: e% d. k - QMainWindow(parent), ui(new Ui::Udp)
8 P% l3 q' X( e( l - {0 i' C8 I$ T* d: a' n$ z6 _
- ui->setupUi(this);. E z, w" e, |2 R1 Y
- udpSocket = new QUdpSocket(this);
% I; D( p c( X - }1 n1 `3 O, U9 I4 H; B: H
- Udp::~Udp()4 q. Y/ Q) y! ^0 d% o$ e# `
- {
+ z/ P- \6 U' A: } - delete ui;' }! |$ h- `. h; q9 K( g' B
- }
0 X! h9 g, ]/ C" m# `3 I& | - /*
# s- G: a& J2 V+ I D4 A# u - * 打开按钮
4 R P2 |7 |& x7 b+ ^9 A - */7 O" y/ w2 Q2 i# n- J! _, p
- void Udp::on_pushButton_clicked()
1 I! b# N% o3 [$ [: `" Z% t - {
9 q G) v. N: o6 O' B( ~ - //绑定本端口的端口号
) P) |, y; q9 S$ y, c1 `/ s6 x - if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){
5 K- J5 F8 @; y% R - QMessageBox::information(this,"提示","成功");
0 k) K; e& U2 _' |3 ? - }else{
) B1 V9 v3 W! N, w+ J) P - QMessageBox::information(this,"提示","失败");
# B- Y2 }% k1 j5 t2 M+ O8 ` - }; s7 _* O! r% {, d" `; o, j9 ?
- //绑定数据信号和槽函数/ q5 ?- s6 L' E: p1 _
- connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));+ E4 h" z, U' |
- }8 a0 e# G" O0 A% P; v
- /*& v L2 O" y; ]- K& v* D% {) r& Y& z2 L
- *读取数据槽函数
* S0 r: p6 ^0 |7 b4 \! u! y: [$ H - */+ Z7 x2 v/ O/ @8 f8 l$ H
- void Udp::readyRead_Slot()
+ M% V( s( E6 P$ j, R5 K - {
, w* W1 j9 H- _4 n1 E* l/ ] - QString buf;4 M2 A( B* d% ]) K) K
- QByteArray array;
, R- q8 }0 F5 B2 ] - //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
! h: }7 q3 z" E! e2 l& ~" C - while(udpSocket->hasPendingDatagrams()){
( m% D$ M8 ]2 f& n - //获取数据
4 f5 t2 D2 H. b1 B9 s; X - array.resize(udpSocket->pendingDatagramSize());
9 n- c4 m/ j- R6 D- u" t3 I - udpSocket->readDatagram(array.data(),array.size());
. v, A* o* ^+ R5 d+ ?; l6 n3 H - buf = array.data();% }" |* X* V; D
- ui->recvEdit->appendPlainText(buf);
5 |0 u1 m- c4 c& S - }7 ]2 v$ g. ]) v" z, a0 k
- }
8 G: t" G% l: r, ? - /*& F; p+ {; f; M( i8 b8 m
- * 发送数据; q4 q- ]6 s3 ]" y6 Q
- */
/ t p& S2 `. U' Z( N5 v: w - void Udp::on_pushButton_3_clicked()7 f% X( r( s. r; M+ F: H
- {
0 h$ \7 _3 s! H4 X1 u; { - quint16 port;
# [7 P8 ~: e8 }' o- B2 c9 y& m1 ` - QString sendBuff;
4 w4 C8 y3 @ ] - QHostAddress address;
" b' T& ?9 k H" Y7 @. _ - address.setAddress(ui->ipEdit->text());//目标机地址2 y. p r+ D2 @
- port = ui->portEdit->text().toInt();//目标机端口号
: w0 x" O' ?9 K2 T - sendBuff = ui->sendEdit->text();//发送的数据
% D4 H$ }6 a7 d; n - //发送2 j+ x, a7 B3 I% Q; y
- udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);
3 ]1 v# E; p" @' E% J - }9 W* p; j6 X4 `2 B, ]5 g0 G2 q. g
- /*% p+ v3 T6 O# Y9 L2 F
- *关闭
- T3 I9 ^4 H- ^2 L, l6 u3 B/ {# `# v! i - */% l+ K2 E1 c+ W. N; q$ g
- void Udp::on_pushButton_2_clicked()
8 K m* }; x) ~! T/ I - {& M, q0 Q; D8 `
- udpSocket->close();
; [8 `. P$ e% Y: ^; U - }
复制代码
: ?& c f2 O! _+ W8 v' L3 b }/ i5 P X
|
|