Qt学习之网络编程(二)

UDP协议

UDP协议(用户数据报协议)是一种简单轻量级、不可靠、面向数据报、无连接的传输层协议。之后我们会介绍TCP协议,相对于UDP,TCP是一种可靠的、有连接的协议;既然这样我们就用TCP不就好了?UDP一直沿用至今是有它的必要意义的,什么意义---UDP它快呀。在进行可靠性并不是需要那么搞得情况下,UDP绝对是首选,比如视频聊天就是UDP协议传输的额,所以有时会出现卡顿的情况,但实际上并不影响我们的使用。下面我们来实现它:
01.png

UDP Server

创建界面

定义好组件

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>

class UdpServer : public QDialog
{
    Q_OBJECT

public:
    UdpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~UdpServer();
    
private:
    QLabel *TimerLabel;
    QLineEdit *TextLineEdit;
    QPushButton *StartButton;
    QVBoxLayout *mainLayout;
};

#endif // UDPSERVER_H

再在udpserver.cpp文件中将界面具体实现:

#include "udpserver.h"

UdpServer::UdpServer(QWidget *parent, Qt::WindowFlags f)
    : QDialog(parent, f)
{
    setWindowTitle(tr("UDP Server"));
    
    TimerLabel = new QLabel(tr("计时器:"),this);
    TextLineEdit = new QLineEdit(this);
    StaratButton = new QPushButton(tr("开始"),this);
    
    mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(TimerLabel);
    mainLayout->addWidget(TextLineEdit);
    mainLayout->addWidget((StartButton));
}

UdpServer::~UdpServer()
{

}

与之前的代码中的QWidget不太相同,这里用的是QDialog,而且代码中QWidget(QWidget *parent=0,Qt::WindowFlags f=0)增加了Qt::WindowFlags。我在这先说一说区别,QWidget *parent=0是父窗口部件的指定,后面的新增组件只用利用this指针附着在上面就行了,如果没有this则会被父窗口遮挡。QT::WindowFlags=0是指定控件的窗口标识,值为0(Qt::Widget)。而窗口标识是由窗口类型和窗口提示hint,首先判断一个控件是否是窗体先根据参数parent的指定,要是值为0那么就可以判断其是一个窗口。否则需要根据Qt::WindowFlags枚举类型的值才可以判断其是否为窗口还是部件。由于Qt::WindowFlags为枚举类型,所以会将QWidget、QWindow、QDialog....组件或者窗口进行枚举,表示窗口或者组件的作用。
实现界面如下图:
02.png

功能实现

首先在udpserver.h中声明public slots,为StartButtonClicked()与timeout()两个方法;之后再在private中声明port、判断是否点击开始了的isStarteddebol变量、一个udp套接字、计时器timer。
然后我们需要在udpServer.cpp中完成StartButtonClicked()与timeout()两个函数。StartButtonClicked()比较简单,只是一个判断让按钮显示“开始”还是“停止”,并将是否点击开始了的isStarteddebol变量置为相应的参数,同时需要开始一个计时器如果timer->start(1000)即1000s过后就自动断开连接。
实现timeout(),之前的connect(..,SIGNAL(timeout()),..,SLOT(timeout()))函数是将信息timeout的数据进行绑定;如果输入的信息位空字符串,则直接返回。QHostAddress::Broadcast指定向广播地址发送,这里是向port发送数据。

UDP Client

同样是创建界面和功能实现两个部分,创建界面就一笔带过了,这里谈谈功能实现中关于套接字实现的这个地方。功能代码如下:

 port = 5555;

    udpSocket = new QUdpSocket(this);
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));

    bool result = udpSocket->bind(port);

首先创建一个udp套接字,然后将套接字绑定在端口5555上,这样服务器端和客户端都有一个端口5555,则可以实现通信。而connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));这句中,代表连接QIODevice的readyRead()信号。QUdpSocket也是一个I/O设备,从QIODevice继承而来,当有关数据到达I/O设备的时候,会发出readyRead()信号。
dataReceived()函数实现代码:

void UdpClient::dataReceived()
{
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());

        udpSocket->readDatagram(datagram.data(),datagram.size());
        QString msg=datagram.data();
        ReceiveTextEdit->insertPlainText(msg);
    }
}

while(udpSocket->hasPendingDatagrams()),这句代码的意思是判断UdpSocket中是否有数据报可读,hasPendingDatagrams()方法在至少有一个数据报可读时返回true,否则返回false.最后一句 ReceiveTextEdit->insertPlainText(msg);的功能是显示代码,中间部分代码是读取第一个数据报。
最终效果图如下:
03.png

04.png

05.png

posted @ 2018-03-13 14:50  MrYun  阅读(1678)  评论(0编辑  收藏  举报