前言:前一篇讲了TCP通信,这篇来看看UDP通信。
这里说明一下,UDP通信中分为三种通信分别为单播、组播和广播,下面将一一为大家介绍。
同样的我们都需要在工程文件中添加network
QT += core gui network
进行UDP通信需要用到的头文件
#include <QUdpSocket>
这里我们把UDP通信分为两个部分写,一个是发送端,另一个是接收端,而发送端中又分为单播、组播和广播三种形式,下面我们先来看看写发送端的代码程序的步骤:
发送端Udpsend的代码:
1、单播
(1)创建套接字
QUdpSocket mSocket;
mSocket = new QUdpSocket();
(2)发送数据到指定的地址和端口号
mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("192.168.137.1"),6677);
参数:ui->textEdit->toPlainText().toUtf8 要发送的消息
QHostAddress("192.168.137.1") 接收端的ip地址
6677 端口号,要和接收端的一致
2、组播,组播和单播的步骤是一样的,只有ip地址处有区别
组播ip地址范围:224.0.0.0-239.255.255.255 例子:mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("224.0.0.100"),6677);
3、广播,广播也只有ip地址和单播有区别
广播地址ip:QHostAddress::Broadcast
例子:mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress::Broadcast,6677);
好了,单播、组播和广播的区别应该都了解了,那么我们就来看发送端(udpsend.cpp)的具体代码:
1 #include "udpsend.h" 2 #include "ui_udpsend.h" 3 4 UdpSend:: UdpSend(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui:: UdpSend) 7 { 8 ui->setupUi(this); 9 10 //初始化创建QUdpSocket对象 11 mSocket = new QUdpSocket(); 12 } 13 14 UdpSend::~ UdpSend() 15 { 16 delete ui; 17 } 18 19 void UdpSend::on_sendBt_clicked() 20 { 21 //单播 22 // qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("192.168.137.1"),6677); 23 24 25 //组播ip地址范围:224.0.0.0-239.255.255.255 26 //qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress("224.0.0.100"),6677); 27 28 //广播 29 qint64 len = mSocket->writeDatagram(ui->textEdit->toPlainText().toUtf8(),QHostAddress::Broadcast,6677); 30 31 32 }
发送端的界面文件我做的很简单,我只做了发送消息框:
看完发送端的代码,我们继续来看接收端的代码(Udprecv)
接收端不管是单播、或者组播还是广播代码都是一样的,下面是写接收端代码的步骤:
1、创建套接字
QUdpSocket mSocket; mSocket = new QUdpSocket();
2、绑定地址和端口号
mSocket->bind(QHostAddress::AnyIPv4,6677); 参数:AnyIPv4 IPv4 6677 端口号,要和发送端的一致
3、等待数据的到来,利用readyRread()
connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
4、读数据
readDatagram(char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0) 参数: data:数据 maxSize:数据的大小 address:QHostAddress类型的地址 port:端口号 例子: void UdpRecv::read_data() { QByteArray array; QHostAddress address; quint16 port; array.resize(mSocket->bytesAvailable());//根据可读数据来设置空间大小 mSocket->readDatagram(array.data(),array.size(),&address,&port); //读取数据 ui->listWidget->addItem(array);//显示数据 //发送反馈数据 }
如果是组播的话还涉及到加入组播和退出组播
加入到组播组 joinMulticastGroup 例子:mSocket->joinMulticastGroup(QHostAddress("224.0.0.100"));
退出组播组 leaveMulticastGroup 例子: mSocket->leaveMulticastGroup(QHostAddress("224.0.0.100"));
来看看接收端(Udprecv.cpp)具体实现的代码
1 #include "udprecv.h" 2 #include "ui_udprecv.h" 3 4 UdpRecv::UdpRecv(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui::UdpRecv) 7 { 8 ui->setupUi(this); 9 10 //创建对象 初始化 11 mSocket = new QUdpSocket(); 12 13 //绑定 14 mSocket->bind(QHostAddress::AnyIPv4,6677); 15 //关联读数据信号readyread 16 connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data())); 17 18 } 19 20 UdpRecv::~UdpRecv() 21 { 22 delete ui; 23 } 24 25 void UdpRecv::read_data() 26 { 27 QByteArray array; 28 QHostAddress address; 29 quint16 port; 30 array.resize(mSocket->bytesAvailable());//根据可读数据来设置空间大小 31 mSocket->readDatagram(array.data(),array.size(),&address,&port); //读取数据 32 ui->listWidget->addItem(array);//显示数据 33 //发送反馈数据 34 35 } 36 37 void UdpRecv::on_checkBox_clicked(bool checked) 38 { 39 if(checked) 40 { 41 //加入组播 42 mSocket->joinMulticastGroup(QHostAddress("224.0.0.100")); 43 } 44 45 else 46 { 47 //退出组播 48 mSocket->leaveMulticastGroup(QHostAddress("224.0.0.100")); 49 50 } 51 52 }
接收端的界面文件我只加了显示接收到的信息和选择是否加入组播的选择按钮
这是发送端和接收分开来写的,此外我也实现了一下发送端和接收端写到同一个文件中
头文件qudpapp.h中的代码
1 #ifndef QUDPAPP_H 2 #define QUDPAPP_H 3 4 #include <QWidget> 5 #include <QUdpSocket> 6 namespace Ui { 7 class QUdpApp; 8 } 9 10 class QUdpApp : public QWidget 11 { 12 Q_OBJECT 13 14 public: 15 explicit QUdpApp(QWidget *parent = 0); 16 ~QUdpApp(); 17 18 private slots: 19 void on_sendSigRb_clicked(); //单播旋转轴 20 void on_sendMulRb_clicked(); //组播选择 21 void on_sendBroadRb_clicked(); //广播选择 22 void on_sendBt_clicked(); //发送按钮 23 24 //=========================================== 25 void on_recvCb_clicked(bool checked); //选择接收 26 void on_recvJoinMulBt_clicked(); //加入组播 27 void on_recvLeaveMulBt_clicked(); //退出组播 28 29 void on_sendMesEdit_cursorPositionChanged();//检测消息框是否有数据 30 void read_data(); 31 32 private: 33 Ui::QUdpApp *ui; 34 QUdpSocket *mSocket; 35 QHostAddress sendaddrees; 36 QString sendPort; 37 38 }; 39 40 #endif // QUDPAPP_H
源文件qudpapp.cpp中的代码
1 #include "qudpapp.h" 2 #include "ui_qudpapp.h" 3 #include <QMessageBox> 4 QUdpApp::QUdpApp(QWidget *parent) : 5 QWidget(parent), 6 ui(new Ui::QUdpApp) 7 { 8 ui->setupUi(this); 9 mSocket = new QUdpSocket();//创建套接字 10 ui->sendBt->setEnabled(false); 11 } 12 13 QUdpApp::~QUdpApp() 14 { 15 delete ui; 16 } 17 18 19 //==========================发送端==================== 20 //单播选择 21 void QUdpApp::on_sendSigRb_clicked() 22 { 23 if(ui->sendPortEdit->text().isEmpty() || ui->sendSigAddrEdit->text().isEmpty()) 24 { 25 QMessageBox::warning(this,"提示","请输入单播ip和端口号"); 26 //ui->sendSigRb->setChecked(false); 27 return; 28 } 29 sendaddrees.setAddress( ui->sendSigAddrEdit->text()); 30 sendPort = ui->sendPortEdit->text(); 31 32 } 33 34 //组播选择 35 void QUdpApp::on_sendMulRb_clicked() 36 { 37 if(ui->sendPortEdit->text().isEmpty() || ui->sendMulAddrEdit->text().isEmpty()) 38 { 39 QMessageBox::warning(this,"提示","请输入组播ip和端口号"); 40 //ui->sendSigRb->setChecked(false); 41 return; 42 } 43 sendaddrees.setAddress( ui->sendMulAddrEdit->text()); 44 sendPort = ui->sendPortEdit->text(); 45 46 } 47 48 //广播选择 49 void QUdpApp::on_sendBroadRb_clicked() 50 { 51 if(ui->sendPortEdit->text().isEmpty() || ui->sendBroadAddrEdit->text().isEmpty()) 52 { 53 QMessageBox::warning(this,"提示","请输入广播ip和端口号"); 54 //ui->sendSigRb->setChecked(false); 55 return; 56 } 57 sendaddrees.setAddress( ui->sendBroadAddrEdit->text()); 58 sendPort = ui->sendPortEdit->text(); 59 60 } 61 62 //发送按钮 63 void QUdpApp::on_sendBt_clicked() 64 { 65 mSocket->writeDatagram(ui->sendMesEdit->toPlainText().toUtf8(),sendaddrees,sendPort.toInt()); 66 67 } 68 69 //检测发送消息对话框中是否有消息 70 void QUdpApp::on_sendMesEdit_cursorPositionChanged() 71 { 72 if(ui->sendMesEdit->toPlainText().isEmpty()) 73 { 74 ui->sendBt->setEnabled(false); 75 } 76 else 77 { 78 ui->sendBt->setEnabled(true); 79 } 80 81 } 82 83 //==========================发送端==================== 84 85 86 //==========================接收端===================== 87 88 //选择接收 89 void QUdpApp::on_recvCb_clicked(bool checked) 90 { 91 if(ui->recvPortEdit->text().isEmpty()) 92 { 93 QMessageBox::warning(this,"提示","请输入端口号"); 94 ui->recvCb->setChecked(false); 95 return; 96 } 97 if(checked) 98 { 99 mSocket->bind(QHostAddress::AnyIPv4,ui->recvPortEdit->text().toInt()); 100 connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data())); 101 ui->recvPortEdit->setEnabled(false); 102 } 103 else 104 { 105 mSocket->close(); 106 ui->recvPortEdit->setEnabled(true); 107 } 108 } 109 110 //加入组播 111 void QUdpApp::on_recvJoinMulBt_clicked() 112 { 113 if(ui->recvMulAddrEdit->text().isEmpty()) 114 { 115 QMessageBox::warning(this,"提示","请输入组播ip"); 116 return; 117 } 118 if(mSocket->joinMulticastGroup(QHostAddress(ui->recvMulAddrEdit->text()))) //加入组播 119 { 120 ui->recvMulAddr->addItem(ui->recvMulAddrEdit->text()); 121 } 122 else 123 { 124 QMessageBox::warning(this,"提示","加入组播失败,请修改ip后继续加入"); 125 //return; 126 } 127 128 } 129 130 //退出组播 131 void QUdpApp::on_recvLeaveMulBt_clicked() 132 { 133 mSocket->leaveMulticastGroup(QHostAddress(ui->recvMulAddr->currentIndex()));//退出组播地址列表当前的组播 134 ui->recvMulAddr->removeItem(ui->recvMulAddr->currentIndex()); //删除组播地址列表中当前的组播地址 135 } 136 137 void QUdpApp::read_data() 138 { 139 QByteArray array; 140 array.resize(mSocket->bytesAvailable()); //将接收数据的array设置成为要接收数据的大小 141 QHostAddress recvaddress; 142 quint16 port; 143 mSocket->readDatagram(array.data(),array.size(),&recvaddress,&port); //读取数据 144 ui->recvList->addItem(array); 145 146 } 147 148 //==========================接收端=====================
界面文件qudpapp.ui
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ui version="4.0"> 3 <class>QUdpApp</class> 4 <widget class="QWidget" name="QUdpApp"> 5 <property name="geometry"> 6 <rect> 7 <x>0</x> 8 <y>0</y> 9 <width>637</width> 10 <height>561</height> 11 </rect> 12 </property> 13 <property name="sizePolicy"> 14 <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> 15 <horstretch>0</horstretch> 16 <verstretch>0</verstretch> 17 </sizepolicy> 18 </property> 19 <property name="windowTitle"> 20 <string>QUdpApp</string> 21 </property> 22 <widget class="QWidget" name="layoutWidget"> 23 <property name="geometry"> 24 <rect> 25 <x>9</x> 26 <y>9</y> 27 <width>394</width> 28 <height>463</height> 29 </rect> 30 </property> 31 <layout class="QVBoxLayout" name="verticalLayout_6"> 32 <item> 33 <layout class="QHBoxLayout" name="horizontalLayout_9"> 34 <item> 35 <widget class="QGroupBox" name="groupBox"> 36 <property name="sizePolicy"> 37 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 38 <horstretch>0</horstretch> 39 <verstretch>0</verstretch> 40 </sizepolicy> 41 </property> 42 <property name="title"> 43 <string>发送端</string> 44 </property> 45 <layout class="QVBoxLayout" name="verticalLayout_3"> 46 <property name="spacing"> 47 <number>0</number> 48 </property> 49 <property name="leftMargin"> 50 <number>0</number> 51 </property> 52 <property name="topMargin"> 53 <number>0</number> 54 </property> 55 <property name="rightMargin"> 56 <number>0</number> 57 </property> 58 <property name="bottomMargin"> 59 <number>0</number> 60 </property> 61 <item> 62 <layout class="QVBoxLayout" name="verticalLayout_2"> 63 <item> 64 <layout class="QHBoxLayout" name="horizontalLayout"> 65 <property name="spacing"> 66 <number>0</number> 67 </property> 68 <item> 69 <widget class="QLabel" name="label"> 70 <property name="text"> 71 <string>端 口 号</string> 72 </property> 73 </widget> 74 </item> 75 <item> 76 <widget class="QLineEdit" name="sendPortEdit"> 77 <property name="sizePolicy"> 78 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 79 <horstretch>0</horstretch> 80 <verstretch>0</verstretch> 81 </sizepolicy> 82 </property> 83 <property name="placeholderText"> 84 <string>请输入端口号</string> 85 </property> 86 </widget> 87 </item> 88 </layout> 89 </item> 90 <item> 91 <layout class="QHBoxLayout" name="horizontalLayout_2"> 92 <property name="spacing"> 93 <number>0</number> 94 </property> 95 <item> 96 <widget class="QRadioButton" name="sendSigRb"> 97 <property name="text"> 98 <string>单播</string> 99 </property> 100 </widget> 101 </item> 102 <item> 103 <widget class="QLineEdit" name="sendSigAddrEdit"> 104 <property name="sizePolicy"> 105 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 106 <horstretch>0</horstretch> 107 <verstretch>0</verstretch> 108 </sizepolicy> 109 </property> 110 <property name="placeholderText"> 111 <string>请输入接收方地址</string> 112 </property> 113 </widget> 114 </item> 115 </layout> 116 </item> 117 <item> 118 <layout class="QHBoxLayout" name="horizontalLayout_3"> 119 <property name="spacing"> 120 <number>0</number> 121 </property> 122 <item> 123 <widget class="QRadioButton" name="sendMulRb"> 124 <property name="text"> 125 <string>组播</string> 126 </property> 127 </widget> 128 </item> 129 <item> 130 <widget class="QLineEdit" name="sendMulAddrEdit"> 131 <property name="sizePolicy"> 132 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 133 <horstretch>0</horstretch> 134 <verstretch>0</verstretch> 135 </sizepolicy> 136 </property> 137 <property name="placeholderText"> 138 <string>请输入组播地址</string> 139 </property> 140 </widget> 141 </item> 142 </layout> 143 </item> 144 <item> 145 <layout class="QHBoxLayout" name="horizontalLayout_4"> 146 <property name="spacing"> 147 <number>0</number> 148 </property> 149 <item> 150 <widget class="QRadioButton" name="sendBroadRb"> 151 <property name="text"> 152 <string>广播</string> 153 </property> 154 </widget> 155 </item> 156 <item> 157 <widget class="QLineEdit" name="sendBroadAddrEdit"> 158 <property name="sizePolicy"> 159 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 160 <horstretch>0</horstretch> 161 <verstretch>0</verstretch> 162 </sizepolicy> 163 </property> 164 <property name="placeholderText"> 165 <string>请输入广播地址</string> 166 </property> 167 </widget> 168 </item> 169 </layout> 170 </item> 171 </layout> 172 </item> 173 </layout> 174 </widget> 175 </item> 176 <item> 177 <widget class="QGroupBox" name="groupBox_2"> 178 <property name="sizePolicy"> 179 <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> 180 <horstretch>0</horstretch> 181 <verstretch>0</verstretch> 182 </sizepolicy> 183 </property> 184 <property name="title"> 185 <string>接收端</string> 186 </property> 187 <layout class="QVBoxLayout" name="verticalLayout_4"> 188 <item> 189 <layout class="QVBoxLayout" name="verticalLayout"> 190 <item> 191 <layout class="QHBoxLayout" name="horizontalLayout_7"> 192 <item> 193 <widget class="QCheckBox" name="recvCb"> 194 <property name="text"> 195 <string>接收</string> 196 </property> 197 </widget> 198 </item> 199 <item> 200 <widget class="QLineEdit" name="recvPortEdit"> 201 <property name="placeholderText"> 202 <string>请输入端口号</string> 203 </property> 204 </widget> 205 </item> 206 </layout> 207 </item> 208 <item> 209 <layout class="QHBoxLayout" name="horizontalLayout_5"> 210 <property name="spacing"> 211 <number>0</number> 212 </property> 213 <item> 214 <widget class="QLineEdit" name="recvMulAddrEdit"> 215 <property name="placeholderText"> 216 <string>输入要加入的组播地址</string> 217 </property> 218 </widget> 219 </item> 220 <item> 221 <widget class="QPushButton" name="recvJoinMulBt"> 222 <property name="maximumSize"> 223 <size> 224 <width>40</width> 225 <height>16777215</height> 226 </size> 227 </property> 228 <property name="text"> 229 <string>加入</string> 230 </property> 231 </widget> 232 </item> 233 </layout> 234 </item> 235 <item> 236 <layout class="QHBoxLayout" name="horizontalLayout_6"> 237 <item> 238 <widget class="QComboBox" name="recvMulAddr"/> 239 </item> 240 <item> 241 <widget class="QPushButton" name="recvLeaveMulBt"> 242 <property name="maximumSize"> 243 <size> 244 <width>40</width> 245 <height>16777215</height> 246 </size> 247 </property> 248 <property name="text"> 249 <string>退出</string> 250 </property> 251 </widget> 252 </item> 253 </layout> 254 </item> 255 </layout> 256 </item> 257 </layout> 258 </widget> 259 </item> 260 </layout> 261 </item> 262 <item> 263 <layout class="QVBoxLayout" name="verticalLayout_5"> 264 <item> 265 <widget class="QListWidget" name="recvList"/> 266 </item> 267 <item> 268 <widget class="QTextEdit" name="sendMesEdit"> 269 <property name="maximumSize"> 270 <size> 271 <width>16777215</width> 272 <height>100</height> 273 </size> 274 </property> 275 </widget> 276 </item> 277 </layout> 278 </item> 279 <item> 280 <layout class="QHBoxLayout" name="horizontalLayout_8"> 281 <item> 282 <widget class="QPushButton" name="clearRecvListBt"> 283 <property name="text"> 284 <string>清除接收区</string> 285 </property> 286 </widget> 287 </item> 288 <item> 289 <widget class="QPushButton" name="clearsendEditBt"> 290 <property name="text"> 291 <string>清除发送区</string> 292 </property> 293 </widget> 294 </item> 295 <item> 296 <spacer name="horizontalSpacer_2"> 297 <property name="orientation"> 298 <enum>Qt::Horizontal</enum> 299 </property> 300 <property name="sizeHint" stdset="0"> 301 <size> 302 <width>40</width> 303 <height>20</height> 304 </size> 305 </property> 306 </spacer> 307 </item> 308 <item> 309 <widget class="QPushButton" name="sendBt"> 310 <property name="text"> 311 <string>发送</string> 312 </property> 313 </widget> 314 </item> 315 </layout> 316 </item> 317 </layout> 318 </widget> 319 </widget> 320 <layoutdefault spacing="6" margin="11"/> 321 <resources/> 322 <connections> 323 <connection> 324 <sender>clearRecvListBt</sender> 325 <signal>clicked()</signal> 326 <receiver>recvList</receiver> 327 <slot>clear()</slot> 328 <hints> 329 <hint type="sourcelabel"> 330 <x>47</x> 331 <y>448</y> 332 </hint> 333 <hint type="destinationlabel"> 334 <x>70</x> 335 <y>227</y> 336 </hint> 337 </hints> 338 </connection> 339 <connection> 340 <sender>clearsendEditBt</sender> 341 <signal>clicked()</signal> 342 <receiver>sendMesEdit</receiver> 343 <slot>clear()</slot> 344 <hints> 345 <hint type="sourcelabel"> 346 <x>134</x> 347 <y>455</y> 348 </hint> 349 <hint type="destinationlabel"> 350 <x>145</x> 351 <y>410</y> 352 </hint> 353 </hints> 354 </connection> 355 </connections> 356 </ui>
界面文件图示