1 简介
参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=61
说明:UDP是面向无连接的,客户端并不与服务器不建立连接,直接向服务器发送数据,服务器端也不从客户端接收连接,只负责调用接收函数,等待客户端连接的到达。
udp通信模型如下:
(1)服务器端
1)创建套接字;
2)绑定套接字;
3)接收或发送数据;
4)关闭连接。
(2)客户端
1)创建套接字;
2)接收或发送数据;
3)关闭连接。
2 测试说明
(1)基本udp测试
功能:创建一个窗口,使用127.0.0.1:8888进行回环测试,自发自收。
实现步骤:
创建套接字并绑定端口,不指定ip:
1 QUdpSocket *udpsocket = NULL; 2 //创建套接字,指定父对象 3 udpsocket = new QUdpSocket(this); 4 //绑定 5 udpsocket->bind(8888);
送数据:
1 //先获取对方的ip和端口 2 QString ip = ui->lineEdit_ip->text(); 3 qint16 port = ui->lineEdit_port->text().toInt(); 4 //获取编辑区内容 5 QString str = ui->textEdit_send->toPlainText(); 6 if (str.isEmpty()) { 7 return; 8 } 9 //给指定的IP发送数据 10 udpsocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
接收数据:
1 //当对方成功发送数据过来,会自动触发readyRead()信号 2 connect(udpsocket, &QUdpSocket::readyRead, 3 [=](){ 4 //读取对方发送的数据 5 char buf[1024] = {0}; 6 QHostAddress cli_addr; //对方地址 7 quint16 port; //对方端口 8 qint64 len = udpsocket->readDatagram(buf, sizeof(buf), &cli_addr, &port); 9 if (len > 0) { 10 //格式化[192.168.2.2:8888]aaaa 11 QString str = QString("[%1:%2] %3").arg(cli_addr.toString()).arg(port).arg(buf); 12 //给编辑区设置内容 13 ui->textEdit_recv->append(str); 14 } 15 } 16 );
完整代码如下:
widget.h
1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 #include <QUdpSocket> 6 7 namespace Ui { 8 class Widget; 9 } 10 11 class Widget : public QWidget 12 { 13 Q_OBJECT 14 15 public: 16 explicit Widget(QWidget *parent = 0); 17 ~Widget(); 18 19 private slots: 20 void on_pushButton_send_clicked(); 21 22 void on_pushButton_close_clicked(); 23 24 private: 25 Ui::Widget *ui; 26 QUdpSocket *udpsocket = NULL; 27 }; 28 29 #endif // WIDGET_H
widget.cpp
1 #include "widget.h" 2 #include "ui_widget.h" 3 #include <QHostAddress> 4 5 Widget::Widget(QWidget *parent) : 6 QWidget(parent), 7 ui(new Ui::Widget) 8 { 9 ui->setupUi(this); 10 setWindowTitle("服务器端口为:8888"); 11 12 //创建套接字,指定父对象 13 udpsocket = new QUdpSocket(this); 14 //绑定 15 udpsocket->bind(8888); 16 //当对方成功发送数据过来,会自动触发readyRead()信号 17 connect(udpsocket, &QUdpSocket::readyRead, 18 [=](){ 19 //读取对方发送的数据 20 char buf[1024] = {0}; 21 QHostAddress cli_addr; //对方地址 22 quint16 port; //对方端口 23 qint64 len = udpsocket->readDatagram(buf, sizeof(buf), &cli_addr, &port); 24 if (len > 0) { 25 //格式化[192.168.2.2:8888]aaaa 26 QString str = QString("[%1:%2] %3").arg(cli_addr.toString()).arg(port).arg(buf); 27 //给编辑区设置内容 28 ui->textEdit_recv->append(str); 29 } 30 } 31 ); 32 } 33 34 Widget::~Widget() 35 { 36 delete ui; 37 } 38 39 void Widget::on_pushButton_send_clicked() 40 { 41 //先获取对方的ip和端口 42 QString ip = ui->lineEdit_ip->text(); 43 qint16 port = ui->lineEdit_port->text().toInt(); 44 //获取编辑区内容 45 QString str = ui->textEdit_send->toPlainText(); 46 if (str.isEmpty()) { 47 return; 48 } 49 //给指定的IP发送数据 50 udpsocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port); 51 } 52 53 void Widget::on_pushButton_close_clicked() 54 { 55 close(); 56 }
运行测试:
(2)UDP广播
概念:使用UDP广播,局域网内的其它UDP用户全部可以收到广播的消息。UDP广播只能在局域网范围内使用。
Qt中在使用writeDatagram()函数发送数据的时候,将第二个参数设置为广播地址QHostAddress::Broadcast就表示UDP广播。
(3)UDP组播
当我们需要发送消息给某些特定用户,或者只接收某些特定用户的消息时,可以使用组播进行实现。
组播地址有:
- 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
- 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
- 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
- 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。
Qt中注册加入到组播地址需要使用QUdpSocket类的成员函数joinMulticastGroup()。
更改上面的代码的bind和加入joinMulticastGroup()函数:
1 //用主播,主要使用ipv4地址 2 udpsocket->bind(QHostAddress::AnyIPv4, 8888); 3 //加入某个组播,组播地址是D类地址 4 udpsocket->joinMulticastGroup(QHostAddress("224.0.0.2"));
测试: