• 24UDP通信


    使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接,只负责调用接收函数,等待来自客户端的数据的到达。

    解析:UDP无需确认对方是否在线,是否能收到。因此服务端也不需要设置监听套接字。双发只需通信套接字即可。Socket绑定指定端口号,其他客户端可以通过该端口号直接进行通信。如:服务端bind(888),而不需要绑定888,也可以直接向服务端发出信息,但是服务端无法向客户端回复(因为不知道客户端端口)。对方发出数据,立即触发信号readyRead,再利用readDatagram接收信息,writeDatagram进行发送信息。

    在UDP通信中,服务器端和客户端的概念已经显得有些淡化,两部分做的工作都大致相同:

    1.创建套接字

    2.绑定套接字,在UDP中如果需要接收数据则需要对套接字进行绑定,只发送数据则不需要对套接字进行绑定。通过调用bind()函数将套接字绑定到指定端口上。

    3.接收或者发送数据

    接收数据:使用readDatagram()接收数据,函数声明如下:

    qint64   readDatagram(char * data, qint64 maxSize,

    QHostAddress * address = 0, quint16 * port = 0)

    参数:

       data: 接收数据的缓存地址

       maxSize: 缓存接收的最大字节数

       address: 数据发送方的地址(一般使用提供的默认值)

       port: 数据发送方的端口号(一般使用提供的默认值)

    使用pendingDatagramSize()可以获取到将要接收的数据的大小,根据该函数返回值来准备对应大小的内存空间存放将要接收的数据。

    发送数据: 使用writeDatagram()函数发送数据,函数声明如下:

    qint64   writeDatagram(const QByteArray & datagram,

    const QHostAddress & host, quint16 port)

    参数:

       datagram:要发送的字符串

       host:数据接收方的地址

       port:数据接收方的端口号

    TCP/IP 和 UDP的区别

    TCP/IP

    UDP

    是否连接

    面向连接

    无连接

    传输方式

    基于流

    基于数据报

    传输可靠性

    可靠

    不可靠

    传输效率

    效率低

    效率高

    能否广播

    不能

    说白了,TCP就是打电话,UDP就是发短信,TCP要确认对方在线并能完整接收,再做出回应。UDP不管对方是否在线,只需最快速率发送给对方,不管对方是否能接收。

    服务端

    UdpServer.h

    #include "udpcilent.h"

    #include "ui_udpcilent.h"

    UdpCilent::UdpCilent(QWidget *parent) :

        QWidget(parent),

        ui(new Ui::UdpCilent)

    {

        ui->setupUi(this);

        this->setWindowTitle("服务端端口:8888");

        ui->Ip->setText("127.0.0.1");

        ui->Port->setText("888");

        m_Client=new QUdpSocket(this);

        //绑定端口号

        m_Client->bind(8888);

        //通信

        connect(m_Client,&QUdpSocket::readyRead,

                [=]()

                {

                    char pBuf[1024]={0};

                    QHostAddress peerIP;

                    quint16 port;

                    //读取对方的信息,端口,IP

                    qint64 size=m_Client->readDatagram(pBuf,1024,&peerIP,&port);

                    //显示在信息框

                    if(size!=-1)

                    {

                        QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                        ui->textEdit_2->setText(strTemp);

                    }

                }

        );

    }

    UdpCilent::~UdpCilent()

    {

        delete ui;

        delete m_Client;

        m_Client=NULL;

    }

    void UdpCilent::on_pushButton_clicked()

    {

        //获取要发送的信息,设置对方的IP,端口号

        QString strSend=ui->textEdit->toPlainText();

        QString peerIP=ui->Ip->text();

        quint16 port=ui->Port->text().toInt();

        //发送

        m_Client->writeDatagram(strSend.toUtf8(),(QHostAddress)peerIP,port);

    }

    void UdpCilent::on_pushButton_2_clicked()

    {

        m_Client->close();

    }

    UdpServer.cpp

    #include "UdpServer.h"

    #include "ui_widget.h"

    #include <QHostAddress>

    #include <QDebug>

    Widget::Widget(QWidget *parent) :

        QWidget(parent),

        ui(new Ui::Widget)

    {

        ui->setupUi(this);

        this->setWindowTitle("服务器端口:888");

        ui->Ip->setText("127.0.0.1");

        ui->Port->setText("8888");

        //分配空间,指定父对象

        m_Server=new QUdpSocket(this);

        //绑定端口号

        m_Server->bind(888);

        //通信

        connect(m_Server,&QUdpSocket::readyRead,

                [=]()

                {

                    char pBuf[1024]={0};

                    QHostAddress peerIP;

                    quint16 port;

                    //读取对方的信息,端口,IP

                    qint64 size=m_Server->readDatagram(pBuf,sizeof(pBuf),&peerIP,&port);

                    //显示在信息框

                    if(size!=-1)

                    {

                        QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                        ui->textEdit_2->append(strTemp);

                    }

                }

        );

    }

    Widget::~Widget()

    {

        delete ui;

        delete m_Server;

        m_Server=NULL;

    }

    void Widget::on_pushButton_clicked()

    {

        //获取要发送的信息,设置对方的IP,端口号

        QString strSend=ui->textEdit->toPlainText();

        QString peerIP=ui->Ip->text();

        quint16 port=ui->Port->text().toInt();

        //发送

        m_Server->writeDatagram(strSend.toUtf8(),QHostAddress(peerIP),port);

    }

    void Widget::on_pushButton_2_clicked()

    {

        m_Server->close();

    }

    同一程序添加两个窗口,且有设计器。新建一个文件,但不是C++类文件,而是QT且带有界面类的,最后在main中使用show()直接显示。如下图:

    客户端

    UdpServer.h

    #ifndef UDPSERVER_H

    #define UDPSERVER_H

    #include <QWidget>

    #include <QUdpSocket>

    namespace Ui {

    class Widget;

    }

    class Widget : public QWidget

    {

        Q_OBJECT

    public:

        explicit Widget(QWidget *parent = 0);

        ~Widget();

    private slots:

        void on_pushButton_clicked();       //发送

        void on_pushButton_2_clicked();     //关闭通信(其实没用)

    private:

        Ui::Widget *ui;

        QUdpSocket *m_Server;   //服务器的通信套接字

    };

    #endif // UDPSERVER_H

    udpcilent.cpp

    #include "udpcilent.h"

    #include "ui_udpcilent.h"

    UdpCilent::UdpCilent(QWidget *parent) :

        QWidget(parent),

        ui(new Ui::UdpCilent)

    {

        ui->setupUi(this);

        this->setWindowTitle("服务端端口:8888");

        ui->Ip->setText("127.0.0.1");

        ui->Port->setText("888");

        m_Client=new QUdpSocket(this);

        //绑定端口号

        m_Client->bind(8888);

        //通信

        connect(m_Client,&QUdpSocket::readyRead,

                [=]()

                {

                    char pBuf[1024]={0};

                    QHostAddress peerIP;

                    quint16 port;

                    //读取对方的信息,端口,IP

                    qint64 size=m_Client->readDatagram(pBuf,1024,&peerIP,&port);

                    //显示在信息框

                    if(size!=-1)

                    {

                        QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                        ui->textEdit_2->setText(strTemp);

                    }

                }

        );

    }

    UdpCilent::~UdpCilent()

    {

        delete ui;

        delete m_Client;

        m_Client=NULL;

    }

    void UdpCilent::on_pushButton_clicked()

    {

        //获取要发送的信息,设置对方的IP,端口号

        QString strSend=ui->textEdit->toPlainText();

        QString peerIP=ui->Ip->text();

        quint16 port=ui->Port->text().toInt();

        //发送

        m_Client->writeDatagram(strSend.toUtf8(),(QHostAddress)peerIP,port);

    }

    void UdpCilent::on_pushButton_2_clicked()

    {

        m_Client->close();

    }

    main.cpp

    #include "UdpServer.h"

    #include <QApplication>

    #include <udpcilent.h>

    int main(int argc, char *argv[])

    {

        QApplication a(argc, argv);

        Widget w;

        w.show();

        UdpCilent u;

        u.show();

        return a.exec();

    }

    程序结果图:

  • 相关阅读:
    jQuery技巧总结
    IBatis.NET框架
    武林足球Ajax全站的核心JS
    Lucene入门与使用(2)转
    图片预加载
    构建基于词典的Lucene分析器
    利用system表来注入
    查看执行后的HTML代码,方便调试
    每日英语
    关于URL的地址重写,自己也实验了一把!
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9215795.html
Copyright © 2020-2023  润新知