以下是基于QT主窗口实现的UDP通信,UDP数据报协议是一个面向无连接的传输层报文协议,它简单易用,不存在TCP协议“粘包”的问题,在强调实时、主动推送的系统中,常常用UDP协议来实现网络双方的通信。UDP发送报文比较随意,可以在程序的任何需要的任何时候和位置发送UDP报文,本文简单实现了一秒发送一次报文
1.在头文件中添加UDP需要的模块,如下:
//UDP通信需要定义的头文件
#include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QUdpSocket>
2.添加网络数据报文的结构定义
/*添加网络数据报文的结构定义*/
#pragma pack(push) //保存对齐状态
#pragma pack(4) //设定为4字节对齐
struct DataStruct{
unsigned int index;
int hour;
int minute;
int second;
int msec;
};
union NetBuffer{
DataStruct data;
char dataBuffer[20];
};
#pragma pack(pop) //恢复字节对齐状态
3.在MainWindow类中定义中添加需要重载的timerEvent定义,添加读取数据报文操作的readPendingDatagrams定义
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void timerEvent(QTimerEvent *event);
public slots:
void readPendingDatagrams();
private:
Ui::MainWindow *ui;
QHostAddress hostAddress; //主机地址
QUdpSocket udpSendSocket,udpRecvSocket;//发送和接收socket
NetBuffer sendBuffer,recvBuffer;//缓冲区
};
#endif // MAINWINDOW_H
4.在MainWindow构造函数中获取本机地址,绑定发送和接收socket,设置响应接收socket接收信号的槽
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//获取本机IP地址
QList<QHostAddress> addressList = QNetworkInterface::allAddresses();
hostAddress = addressList.at(0);
//网络端口绑定
udpSendSocket.bind(hostAddress,3407);
udpRecvSocket.bind(hostAddress,3408);
//设定定时器
this -> startTimer(1000);
//初始化发送计数器
sendBuffer.data.index = 0;
//建立接收socket的连接
QObject::connect(&udpRecvSocket,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
}
5.在源文件中实现发送和接收操作,并在列表中显示,发送操作是在定时器事件响应函数中实现的
void MainWindow::timerEvent(QTimerEvent *event)
{
QTime tm = QTime::currentTime();
sendBuffer.data.hour = tm.hour();
sendBuffer.data.minute = tm.minute();
sendBuffer.data.second = tm.second();
sendBuffer.data.msec = tm.msec();
udpSendSocket.writeDatagram(sendBuffer.dataBuffer,sizeof(sendBuffer),hostAddress,3408);
QString displayString;
displayString = QString("Index = %1 \n Time = %2:%3:%4:%5 \n")
.arg(sendBuffer.data.index)
.arg(sendBuffer.data.hour,2,10,QChar('0'))
.arg(sendBuffer.data.minute,2,10,QChar('0'))
.arg(sendBuffer.data.second,2,10,QChar('0'))
.arg(sendBuffer.data.msec,3,10,QChar('0'));
ui->listWidget->insertItem(0,displayString);
sendBuffer.data.index++;
}
6.在readPendingDatagrams曹中,接收数据并显示
void MainWindow::readPendingDatagrams()
{
QHostAddress sender;
quint16 senderPort;
udpRecvSocket.readDatagram(recvBuffer.dataBuffer,sizeof(recvBuffer),&sender,&senderPort);
QString displayString;
displayString = QString("Index = %1 \n Time = %2:%3:%4:%5 \n")
.arg(recvBuffer.data.index)
.arg(recvBuffer.data.hour,2,10,QChar('0'))
.arg(recvBuffer.data.minute,2,10,QChar('0'))
.arg(recvBuffer.data.second,2,10,QChar('0'))
.arg(recvBuffer.data.msec,3,10,QChar('0'));
ui->listWidget_2->insertItem(0,displayString);
}
7,实现效果如下:
8.源码地址:基于QT主窗口的UDP通信有代码