欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UDP通信之窗口实现

程序员文章站 2022-06-30 19:58:53
...

UDP面向窗口通信的简单实现

介绍:UDP数据报文协议是面向无连接的传输层报文协议。UDP主要用在强调实时,主动推送的系统中,不存在“粘包”情况。

step1.新建界面工程,添加列表部件,用于显示和接收数据。

UDP通信之窗口实现


step2.在头文件中,添加包含QNetwordInterface,QHostAddress,QudpSocket模块,添加网络数据报文的结构定义,重载的timerEvent定义,添加接收数据报文操作定义,定义主机地址,定义发送和接收的socket与缓冲区。

//数据报文结构
#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)   //恢复字节对齐状态


public:
    //重载定时器触发执行操作
    void timerEvent(QTimerEvent * event);
public slots:
    //读取数据报文操作
    void readPendingDatagrams();
private:
    //定义主机地址
    QHostAddress hostAddress;
    //发送与接收socket
    QUdpSocket udpSendSocket,udpRecvSocket;
    //发送与接收缓冲区
    NetBuffer sendBuffer,recvBuffer;

step3.在构造函数中获取本机地址,绑定发送和接收socket,设置响应接收socket接收信号的槽

    //获取本机IP地址
    QList<QHostAddress> addressList = QNetworkInterface::allAddresses();
    hostAddress = addressList.at(0);
    //网络端口绑定
    udpSendSocket.bind(hostAddress,7000);
    udpRecvSocket.bind(hostAddress,7001);
    //设置定时器
    this->startTimer(5000);
    //初始化计数器
    sendBuffer.data.index = 0;
    //建立接收socket的连接
    QObject::connect(&udpRecvSocket,SIGNAL(readyRead()),
                     this,SLOT(readPendingDatagrams()));
注意:readyRead()信号是在有进入的数据被读取时,此信号被发送,即接收socket一有数据报文包,槽函数即被调用进行数据读取和显示。


step4.实现发送与接收操作,并在界面上显示,数据发送为一秒发送一次。这里使用联合的方式解析网络数据结构。

//在timeEvent中设置发送数据并显示
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,7001);
    QString displayString;
    displayString = QString("Index:%1\nTime=%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++;

}

//在槽中接收数据并显示
void MainWindow::readPendingDatagrams()
{
    QHostAddress senderIP;
    quint16 senderPort;
    udpRecvSocket.readDatagram(recvBuffer.dataBuffer,sizeof(recvBuffer),&senderIP,&senderPort);
    QString displayString;
    displayString = QString("Index:%1\nTime=%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,2,10,QChar('0'));
    ui->listWidget_2->insertItem(0,displayString);

}


step5.在*.pro文件中添加QT += core gui network