|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合。
/ I' V8 e" z/ {) ]) ^* ^% eudp 网络编程只需要使用一个类 QUdpSocket。) [1 Y$ J$ X% F4 D, l7 Q( i; c5 `
2 K; p" E5 Y% p2 p本实验中对 QUdpSocket 的基本使用:! F$ H e9 X) J! E* v
1.创建 QUdpSocket 对象。& F9 I; I# r4 `
2.绑定端口号
/ Y# J, ~9 C3 n {- r% Z3.数据到来触发 readyRead()信号。
7 D. ?9 e G6 s4.读取发送数据。* f+ z4 R- G1 j# H2 c% S; Y
5.关闭。
/ I- k0 y6 @- V( P. Y, x* n/ k具体步骤:
8 l1 H9 p4 L! c% P* e步骤一:组装 ui 界面,和 TCP 章节搭建 UI 界面方法一致。( |4 ?# }6 w: H& g) k( r( I
4 ~( f5 F: d4 E O9 k
步骤二:编写代码, D1 K. r8 p, g9 i
1.创建 QUdpSocket 对象,使用 bind 函数绑定端口号和套接字,数据报到来后会发出信 号
7 }2 [. U. a( p(),在绑定的槽函数内去读取数据。# y/ w9 S, q* `! T# z9 W
2.读取数据,数据到来 hasPendingDatagrams()返回 true,再用 pendingDatagramSize()获取数据报的长度,如果数据没有被读取# k( J) T; o& Z7 e" K5 c9 L0 M+ Q% z) z+ i
完,hasPendingDatagrams()就会返回 true,直至数据都被读取完。0 D9 A; u( m/ e2 I D# X6 \0 i- C; Z c
readDatagram(data,size);
6 A+ D d& Y5 {4 H6 }' ]( J参数 data 为读取的数据,size 为数据长度。
9 [# o: F6 [2 F$ n, S3.发送数据,使用 writeDatagram 函数,
6 Q& {2 W$ u0 {+ `writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);
$ l4 G* J7 B& ~$ i3 A% _6 m. {0 ]Data:发送的数据。+ Q! M5 j0 X' U9 r) D) h, l2 C
Len:发送的数据长度。. l% J* J) ^+ |# Z5 L
Host:目标 IP 地址。
( p r5 f- E; FPort:目标端口号。
7 l7 S3 D9 F" M* h1 Y4.关闭 socket 套接字。
5 x% D& ]. D& B- c! N代码如下:
& T) |( I+ c8 _/ E- a' n- udp.h1 B0 p0 f$ \9 |- u: L; ~
- #include <QMainWindow>7 J* t+ s( h, x- `0 y W
- #include <QUdpSocket>' U! `0 |; q# W6 I) Z% q
- namespace Ui {6 G9 W `) c: x: P/ a7 x6 I
- class Udp;, x% n2 u5 q; }5 O
- }
+ E. o# E# M5 ^+ d$ ~# |, j - class Udp : public QMainWindow
, k7 W) N+ s) q6 ~/ [8 F - {* ~# J" Z% c: w3 n0 \
- Q_OBJECT" |! h1 c5 Q$ p. a8 W8 N+ \7 l
- public:9 x z& u; F1 n0 O1 d @2 J* s
- explicit Udp(QWidget *parent = 0); ~Udp();8 f' t8 Y7 c2 w7 P
- QUdpSocket * udpSocket;# d! o, }9 e& q( s5 H; K; b' K
- private slots:
3 _2 ]' k) R! D' K% B - void on_pushButton_clicked();2 v; F ^5 `% x8 { k& b
- void readyRead_Slot(void);
' Z* w( y+ d2 t' d - void on_pushButton_3_clicked();. Y0 i8 w H& Y8 n$ S1 K
- void on_pushButton_2_clicked();8 `) l& ?& x' C8 `
- private:
. h% [: I, x5 w+ a9 R5 H7 W - Ui::Udp *ui;
! E/ k7 T( W3 ~; g$ y2 B0 U$ S/ u - };
) r' \; `8 v9 z& @, R - udp.cpp:
0 m+ Z( V2 y. v5 Q - Udp::Udp(QWidget *parent) :
: |0 \9 s% n. f; z1 f - QMainWindow(parent), ui(new Ui::Udp)
7 _% N3 b% i# N! ]9 j( V" i5 R- S - {% }; |+ R/ N* F
- ui->setupUi(this);# X9 q4 }) k/ G2 ^7 E& D
- udpSocket = new QUdpSocket(this);" A; s# b7 J# ^- T
- }. E% q1 {, e4 m1 ~) e
- Udp::~Udp()
$ p$ E8 A4 q4 h - {& Q- F" |4 J7 l2 c3 ]! C
- delete ui;9 ]: \- ]* f! f5 I
- }8 R& q/ r/ _) b1 b* J+ @" e
- /*+ u; W4 P) F/ T6 O$ Q! F' f
- * 打开按钮) E' b1 }+ c+ O2 N6 @, J" F# u
- */+ ^7 _1 Q1 M5 |' l
- void Udp::on_pushButton_clicked()2 B7 J& a3 q! A& A8 E
- {' f+ x; z/ }7 y& E
- //绑定本端口的端口号# i/ p/ L7 L8 f/ k) i& x* ^6 b
- if(udpSocket->bind(ui->cliEdit->text().toUInt()) == true){/ c L+ M3 f9 x3 l0 ^% l, l7 I
- QMessageBox::information(this,"提示","成功");" ~! b% V5 K6 U7 `+ m' Q+ ~
- }else{4 I' Z& B& |5 e) Z3 x. n! F( ^
- QMessageBox::information(this,"提示","失败");& V1 M2 Q. y3 f) t! w3 s" G1 n
- }
8 l: ~( E; y6 N. ` - //绑定数据信号和槽函数
$ V# z6 O5 `9 S: y - connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));( V" v- |) a; p/ R* O7 e
- }, M/ o3 T, g) [, R0 X5 |
- /*
. D0 C* D% D! _2 F9 ~7 |. N0 T - *读取数据槽函数( y! A3 Y1 B7 F: K. y& _
- */' w9 m5 N9 l z5 X4 b4 c
- void Udp::readyRead_Slot()
1 S3 P+ P; s$ D/ i1 S - {1 u, z1 L* K; B q; L+ v
- QString buf;
" J9 X. m9 M8 |! f - QByteArray array;
F4 p- b* e5 q) d% O9 [2 W0 f' W @ - //hasPendingDatagrams()返回 true 时表示至少有一个数据报在等待被读取! [# d; n: _7 [; p# y9 N' [
- while(udpSocket->hasPendingDatagrams()){0 h7 c7 k5 [6 @- ?
- //获取数据
8 Y5 I1 {3 _: J5 U - array.resize(udpSocket->pendingDatagramSize());
8 j0 ^3 c$ x: Y9 U' s3 z - udpSocket->readDatagram(array.data(),array.size());/ \* S J6 C/ I0 d8 i( z' y& H" `2 T
- buf = array.data();
; X7 r5 s- e5 K- K0 R, F n4 R J - ui->recvEdit->appendPlainText(buf);
2 m& r; x7 [1 K9 B [( b$ v - }
4 W Q* w0 ?8 G/ D) p! c' U$ Q - }
4 d: E/ ?! e7 I" {/ o6 B- y& ~ - /*
- C- ?1 N" |, s0 l+ P; s7 A - * 发送数据6 i: W! s5 Z( t
- */# [: Q" O5 i0 A; |& l0 V2 }6 x$ M
- void Udp::on_pushButton_3_clicked()
% `+ u: U* g) u' w2 v - {
8 z. q5 ]9 ?, C' ]$ c - quint16 port;9 W/ f) I7 \3 Z9 x( R
- QString sendBuff;
) o O& s1 W: { - QHostAddress address;( V% p; S0 I' ~+ w) Q7 h1 ]
- address.setAddress(ui->ipEdit->text());//目标机地址 g a1 @) w% F- v( W( ~/ N$ {4 [
- port = ui->portEdit->text().toInt();//目标机端口号
1 `1 X. F" a6 p+ ~ - sendBuff = ui->sendEdit->text();//发送的数据
* M+ @5 {6 X2 J' n; s - //发送+ X# q) L$ k9 R; @9 h' |/ U2 o1 R
- udpSocket->writeDatagram(sendBuff.toLocal8Bit().data(),sendBuff.length(),address,port);$ `" B; _7 B3 W9 l
- }
( i! a# ^% E4 t: n - /*
0 l( l8 D. Z, E! i9 d* M - *关闭
4 n" u7 F, j* m$ s1 B0 M - */! N( ]" Y; |3 S9 m
- void Udp::on_pushButton_2_clicked()- `! g+ i( a: H7 K
- {
# W( t3 g+ L( O3 e" K - udpSocket->close();/ N" u* R) x4 b& D. e+ B
- }
复制代码
, l# C0 W2 t. x( \: d/ B
+ _$ P6 _+ z( l" _2 q& h5 J& U
|
|