|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。
' X2 I0 h& B# p9 F) y' ?+ }" P- `udp 网络编程只需要使用一个类 QUdpSocket。
$ z# a; U, E. W! B7 L
, Y4 u& f% W( X' [
本实验中对 QUdpSocket 的基本使用:
: F& n+ p- ^/ a) j3 R* ~5 F w& s& ]1.创建 QUdpSocket 对象。. D3 h- N$ W4 a7 x
2.绑定端口号
- s6 t/ r" [0 `6 h/ J3.数据到来触发 readyRead()信号。
i' D3 U- }/ y- R4.读取发送数据。
& j$ b: G9 g0 d( V9 @: e" K5.关闭。) r; S+ g# H6 h9 h- p6 V
具体步骤:
6 L: L0 Z/ J0 K+ Z2 Z* ^步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。. W ~& A. }: E* k6 L, N
: Y' k1 \1 J6 E K* N, |0 _9 I
步骤二:编写代码
/ Z% y/ d3 @5 w* @1 |1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号% n, A! O) f g l: V
(),在绑定的槽函数内去读取数据。
* S$ K) U% L/ t. x* S/ e2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取
& A1 L( S2 Y) B& p4 B2 O$ n- R/ K& u完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。
0 a+ _. q1 w4 E9 a' L p& @) n, GreadDatagram(data,size);
6 B0 a" }9 @( `0 M% X参数 data 为读取的数据,size 为数据长度。
8 j2 A7 n, P- J! l& w3.发送数据,使用 writeDatagram 函数,
" V1 R! v9 k- xwriteDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);$ A) |) d2 x/ y5 w! `9 O5 V3 w
Data:发送的数据。
0 W' u" E" ^! m) A7 }. v kLen:发送的数据长度。* l# M/ r6 h4 R9 O6 B+ n7 L
Host:目标 IP 地址。
7 B. J; Y1 x. v+ Q Z+ [Port:目标端口号。
n* S8 C% O+ R/ T, E4.关闭 socket 套接字。
6 E8 ]8 |- ~7 Y代码如下:5 U) T9 B* a4 x' O5 C* Q
- udp.h
% W( W9 I# V9 K/ ^5 y" G - #include <QMainWindow>+ O/ F J! H. M
- #include <QUdpSocket>" ^2 i5 I$ p R7 N/ g
- namespace Ui {
( c: ?5 I% a3 P. Q - class Udp;
3 w* ]) f+ Q5 j1 I6 i - }9 b! l; @8 P% C. i6 i5 i
- class Udp : public QMainWindow
! ~5 O/ C+ D0 M4 k- @ - {/ D4 M5 g2 a- ^/ D' n" c
- Q_OBJECT) a9 f3 N8 N5 K; c$ `2 e
- public:% _; `% b4 v% [' \* p) H h/ \
- explicit Udp(QWidget *parent = 0); ~Udp();5 Y6 t& k; ?1 a& n* G% ~
- QUdpSocket * udpSocket;
[: ]) L8 X: s# i5 U' t' X - private slots:3 _* C9 m' v& P$ \
- void on_pushButton_clicked();
' R3 p% X& \8 M8 M/ G, p: R/ t+ W - void readyRead_Slot(void);$ p; n, ]" G1 |; i# }/ r( H
- void on_pushButton_3_clicked();! t" M* {3 H+ M" j2 t* Z( ]
- void on_pushButton_2_clicked();
; Z6 x- x6 j% S( S - private:
1 r, W4 |5 d X2 } E - Ui::Udp *ui;7 B7 e, {" a, V! Q
- };5 f1 l6 @ D/ h) U/ v% @3 C
- udp.cpp:
: H# S3 e" r8 [ - Udp::Udp(QWidget *parent) :7 y& M1 B1 u- v; W G
- QMainWindow(parent), ui(new Ui::Udp)- }5 [6 n. L( I. {; X' d: [8 v3 V
- {
/ b# z2 C( [1 O8 K0 S1 ]8 N - ui->setupUi(this);! [0 G1 E( n( u2 V
- udpSocket = new QUdpSocket(this);
4 g J7 E: q2 J6 G0 T: {) _3 A$ @ - }& _# M% p& N8 _. x5 y8 t+ {
- Udp::~Udp()
% C+ y, T) R: t6 E0 {$ b - {2 K" k1 O7 E Q( h2 C
- delete ui;8 g! V) P3 H0 S- f1 T
- }
% j$ `1 ]) N% {- K, }8 y# a4 I - /*
* S* H9 B( l5 L4 x* ^ - * 打开按钮
0 C' X4 X" `7 ?/ I- K5 x - */8 R. S2 n7 }: c9 m. n: J& i
- void Udp::on_pushButton_clicked()
, s/ K4 E6 p3 F. m) q - {
5 q3 F0 u/ m8 t: S - //绑定本端口的端口号4 k8 _# x- y% G E$ [
- if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){) O! m7 o' i5 j( q3 w3 A) A4 }
- QMessageBox::information(this,"提示","成功");9 L8 e, J8 T" Z
- }else{7 I# e( E& n4 w* \9 ?( `/ u" L! R2 _
- QMessageBox::information(this,"提示","失败");* }, ` a! Y& | A: D
- }: v/ _+ \6 w5 ~% }
- //绑定数据信号和槽函数
* O3 h, I+ T* j4 N( E* `# r - connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));0 [' {* L4 T; A8 L: a" f$ \
- }1 o! u0 c" \- t4 Q
- /*
' Z/ X% e6 I# W: L - *读取数据槽函数
3 J: D1 W3 b' k. w - */0 p- _9 Z i' ?% h
- void Udp::readyRead_Slot()6 e. l. }. @$ I& S a* @
- {
( M- v/ b9 ~+ b9 V - QString buf;
6 E$ W9 e5 i" z' v; Y# J* m - QByteArray array;
( y' H7 o( i7 `/ A/ q8 a - //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取
( u+ c& Q% h: L" k" n - while(udpSocket->hasPendingDatagrams()){6 d0 } i/ }6 d% o( L' y; |
- //获取数据
, c8 N7 i- b Y' E( {3 L9 ]; w/ k - array.resize(udpSocket->pendingDatagramSize());$ s! c8 `5 j5 t, o6 F5 t$ o- \
- udpSocket->readDatagram(array.data(),array.size());
$ H: O1 {* _) K, E, ?* O9 V+ U - buf = array.data();
. A' Q( l! G2 L; I" e; @ F - ui->recvEdit->appendPlainText(buf);1 Z" z/ ]! v( V( }% W
- }
$ B. {4 k% M+ t& Z3 {: k( R# o; F3 U# f$ t - }
+ Y& d* ]' r9 q0 n: t - /*9 I1 [+ j3 p1 q, u$ t& O; W
- * 发送数据 l. U! e' K" O" I' U I, d
- */8 Y, }0 C' L& S* d' W% k
- void Udp::on_pushButton_3_clicked(). K, |) L f7 f7 O* g: G8 P
- {
# R' u% t, y( s - quint16 port;
W+ p6 I, x+ S5 h8 m - QString sendBuff;' z2 k Z& \2 y
- QHostAddress address;
9 w3 c2 D7 d! e0 }* b - address.setAddress(ui->ipEdit->text());//目标机地址
& e9 {$ G0 d- r0 @5 A - port = ui->portEdit->text().toInt();//目标机端口号, F" z; Q" u9 h* c2 ~% d9 T
- sendBuff = ui->sendEdit->text();//发送的数据
3 }) u( l; `1 I0 H - //发送! r: j+ j4 f- t; m i0 \% X+ p! b
- udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);
* @; \) M0 l: ^% h( {" X% ^3 C - }. B7 |* j" y. R2 c! {- I
- /*$ A9 O! m; h8 j6 L4 f7 ~1 r% ^
- *关闭
/ `7 E- M- l, c. L6 ^; K - */2 N; b" |; B' q4 `
- void Udp::on_pushButton_2_clicked()0 N' G, D" h( [3 ?/ t$ h
- {
h, I) m" O8 f: @4 d4 a6 d# s0 f3 y - udpSocket->close();- L* O( ^; }2 {) t% p
- }
复制代码
7 } N! L9 u% c
6 h) ^ V: u3 D' r( |' ` |
|