Qt之UDP编程实验(1)
该程序为QT自带Demo,工程名为broadcast receiver,展示了在一个如何在本地局域网中接收UDP广播的信息。
broadcastreceiver.pro
HEADERS = receiver.h SOURCES = receiver.cpp \ main.cpp QT += network
receiver.h
#ifndef RECEIVER_H #define RECEIVER_H #include<QWidget> class QLabel; class QPushButton; class QUdpSocket; class Receiver:public QWidget { Q_OBJECT public: Receiver(QWidget *parent=0); private slots: void processPendingDatagrams(); private: QLabel *statusLabel; QPushButton *quitButton; QUdpSocket *udpSocket; }; #endif // RECEIVER_H
receiver.cpp
#include<QtGui> #include<QtNetwork> #include"receiver.h" Receiver::Receiver(QWidget *parent):QWidget(parent) { statusLabel=new QLabel(tr("Listening for broadcasted messages")); statusLabel->setWordWrap(true);//设置为可换行 quitButton=new QPushButton(tr("&Quit")); udpSocket=new QUdpSocket(this); /*QUdpSocket::ShareAddress表明其他服务也可以绑定在这个端口上*/ udpSocket->bind(45454, QUdpSocket::ShareAddress); connect(udpSocket,SIGNAL(readyRead()),this,SLOT(processPendingDatagram())); connect(quitButton,SIGNAL(clicked()),this,SLOT(close())); QHBoxLayout *buttonLayout=new QHBoxLayout(); buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); buttonLayout->addStretch(1); QVBoxLayout *mainLayout=new QVBoxLayout(); mainLayout->addWidget(statusLabel); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setWindowTitle(tr("Receiver")); } void Receiver::processPendingDatagrams() { while(udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(),datagram.size()); statusLabel->setText(tr("Received datagram:\"%1\"").arg(datagram.data())); } }
main.cpp
#include<QApplication> #include"receiver.h" int main(int argc,char *argv[]) { QApplication app(argc,argv); Receiver receiver; receiver.show(); return app.exec(); }
运行结果:
一、概述:
#include <QUdpSocket>
QUdpSocket类继承自QAbstractSocket,该类中的所有函数都是可重入的(reentrent)。
二、介绍
QUdpSocket描述:
QUdpSocket提供了UDP套接字API,用来接收和发送UDP数据报。
QUdpSocket类最通用的使用方式是:用bind()函数绑定一个IP地址和端口Port,然后调用writeDatagram()和readDatagram()函数传输数据。如果要使用QIODevice中的read(), readLine(), write()等函数,必须首先调用connectToHost()函数,直接建立一个和对方的连接。
只要向网络写入了一个数据报,SOCKET就产生一个bytesWritten()信号,如果仅仅是发送数据报,无需调用bind()。
数据报到来,readyRead()信号被产生,此时hasPendingDatagrams()函数返回真(true)。调用pendingDatagramSize()获取第一个数据报的长度(size),readDatagram()读取数据报内容。
注意:接收到readyRead()信号后,应当读取该数据报,否则下一个数据报到来后将不再产生readyRead()信号。
QUdpSocket类也支持UPD组播(multicast)。joinMulticastGroup()和leaveMulticastGroup()用来控制组成员,QAbstractSocket::MulticastTtlOption和QAbstractSocket::MulticastLoopbackOption分别用来设置socket的TTL和回环(loopback)选项,setMulticastInterface()用来为组播数据报设置对外接口,multicastInterface()来获取该接口类型:IP_MULTICAST_IF对应IPv4,IPV6_MULTICAST_IFIPv6。
通过QUdpSocket类,还可以使用connectToHost()建立和UDP服务器的虚拟连接,然后使用read()和write()交换数据,而不必为每一个数据报都指定接收者(receiver)。
三、标志成员含义
BindFlag:
这些值可以组成不同的标志,传递给QUdpSocket::bind()函数来修改bind()的特性。
enum BindFlag {ShareAddress, DontShareAddress, ReuseAddressHint, DefaultForPlatform }
常量定义 | 值 | 描述 |
QUdpSocket::ShareAddress | 0x1 |
1、允许其他服务绑定同样的地址和端口。 3、需要注意的是,把该选项和ReuseAddressHint结合,也会允许你的服务重新绑定一个已存在的共享地址 4、在Unix上,该选项等同于SO_REUSEADDR;在Windows上,该选项被忽略 |
QUdpSocket::DontShareAddress | 0x2 |
1、采用专有的方式绑定某个地址和端口,其他任何服务都不能再重新绑定
2、通过该选项,确保绑定成功,指定的服务将是地址和端口唯一监听者,就算是拥有ReuseAddressHint的服务也不允许重新绑定
3、在安全性上,该选项优于ShareAddress,但是在某些操作系统上需要管理员的权限才能运行
4、在Unix和Mac OS上,绑定地址和端口的默认行为是非共享,所以该选项会被忽略;在Windows上,等同于SO_EXCLUSIVEADDRUSE套接字选项
|
QUdpSocket::ReuseAddressHint | 0x4 |
1、为QUdpSocke提供提示,即在地址和端口已经被其他套接字绑定的情况下,也应该试着重新绑定
2、在Unix上,该选项被忽略;在Windows上等同于SO_REUSEADDR 套接字选项
|
QUdpSocket::DefaultForPlatform | 0x0 |
1、当前平台的默认选项
2、在Unix和Mac OS上,该选项等同于DontShareAddress + ReuseAddressHint;在Windows上等同于ShareAddress
|