Qt之udp通信

一、UDP的特点

UDP(用户数据报协议)是一种简单轻量级、不可靠、面向数据报,无连接的传输层协议。

二、UDP适合应用的几种情况

1、网络数据大多为短消息

2、拥有大量客户端

3、对数据安全性无特殊要求

4、网络负担非常重,但对响应速度要求高。

三、利用UDP进行通信

因为UDP是无连接,所以通信不需要建立连接,只要知道对方的IP地址和端口号就行了。

(1)首先需要绑定端口号,用到bind函数(如果同一台电脑之间测试可以不绑定端口号)

udpsocket->bind(8000);

(2)接收数据部分

接收到数据的时候,socket会自动触发readyRead这个信号,所以需要有一个函数来处理这个信号,也就是读取socket接收到的数据。提供了读取的函数:readDatagram

readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)

参数详情:

1、将读取的内容存放在data中

2、读取的长度

3、对方的ip地址

4、对方的端口号

(3)发送数据部分

发送数据的步骤和读取数据的步骤差不多的,用到了writeDatagram()这个函数来发送

writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)

参数详情:

1、需要发送的消息

2、对方的IP地址

3、对方的端口号

贴个小例子:

//创建套接字
QUdpSocket *udpsocket= new QUdpSocket;

//绑定端口
bool result = udpsocket->bind(LocalPort,QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);
if(result)
{
    udpsocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,1024*1024*8);//设置缓冲区
    //连接接收信号槽     
    connect(udpsocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    //发送数据 目的地址:serverIP  目的IP:serverPort
    QByteArray line;
    line.resize(2);
    line[0] = 0x02;
    line[1] = 0x7d;
    udpsocket->writeDatagram(line.data() , QHostAddress(serverIP),serverPort);
void dataReceived()
{
    while (udpsocket->hasPendingDatagrams())
       {
           QByteArray datagram;
           datagram.resize(udpsocket->pendingDatagramSize());
           udpsocket->readDatagram(datagram.data(),datagram.size());
           qDebug()<<"data ;"<

断开连接:

udpsocket->disconnected();
delete udpsocket;
udpsocket= nullptr;

下面介绍udp的组播(Multicast)

组播的原理大致就是服务器往某一组播地址和端口发数据,之后客户端从指定的组播地址和端口去取数据,好处就是减轻了服务器发送的压力,弊就是只要是加入到组播组的用户都可以收到数据,如果往同一组播地址和端口发送数据的话,可能会引起问题。

下面是服务器加入到组播,其实就是用了joinMulticastGroup()函数

QUdpSocket *udpsocket= new QUdpSocket;

//绑定本地端口
udpsocket->bind(QHostAddress::AnyIPv4, multicastPort, QUdpSocket::ShareAddress);

//加入组播组
bool result = udpsocket->joinMulticastGroup(QHostAddress(multicastIP));
if(result)
{
    //设置缓冲区
    udpsocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,1024*1024*8);
    //连接接收信号槽     
    connect(udpsocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
}

下面就和普通udp连接类似,在槽函数里读取数据,做些想做的操作。

也可以开启多个服务器,用客户端发送数据,所有服务器端都会收到客户端发送的数据。

组播的注意点:

(1)发送端既可以加入组播,也可以不加入组播;

(2)服务端绑定的ip地址必须是ipv4地址,像QHostAddress::Any即是ipv4地址

(3)组播ip必须是D类ip。

贴一点项目的UDP实例代码

#include

class UdpServer:public QObject
{
    Q_OBJECT

public:
    UdpServer(int port);
    virtual ~UdpServer();

    //开始监听
    bool startListen();
    
    //广播message到port上
    static int broadCast(const QString &message, int port);

protected:
    virrtual bool doMessage(const QString &data) = 0;

private:
    bool init(int port);

private slots:
    void readpendingDatagrams();

private:
    QUdpSocket * m_socket;
    bool m_isInit;
    int m_port;     //广播端口 
};
Udpserver::Udpserver(int port):
    m_isInit(false)
{
    m_socket = new QUdpSocket(this);
    m_port = port;
}

Udpserver::~Udpserver
{
    delete m_socket;
}

bool Udpserver::startListen()
{
    
}

int Udpserver::broadCast(const QString& message, int port)
{
    static QUdpSocket udp;
    QByteArray datagram = message.toUtf8();
    int ret = udp.writeDatagram(datagram .data(), datagram.size(),
                                QHostAddress::BroadCast, port);
    
    if(!ret)
    {
        Qstring str = QStringLiteral("发送失败");
    }
    
    return ret;
}

bool Udpserver::init(int pot)
{
    if(m_socket->bind(QHostAddress::any,port))
    {
        m_isInit = connect(m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagram()));

        return m_isInit;
    }
    return false;
}

void Udpserver::readPendingDatagram()
{   
    while(m_socket->hasPendingDatagram())
    {
        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        
        m_socket->readDatagram(datagram.data(), datagram.size(),
                                &sender, &senderPort);

        if(!domessage(datagram))
        {
            qDebug()<<"error";
        }
    }
}

你可能感兴趣的:(Qt,Qt)