通俗易懂玩QT:QUdpSocket学习

QT之QUdpSocket学习

最近,因为公司的业务需求,需要用到 socket 的 udp 通信协议,特意学习了一下,这里分享给大家。

一、QT 的 socket 家族

这里首先给大家介绍一下 QT 的 socket 家族,结构图大致如下图所示:
通俗易懂玩QT:QUdpSocket学习_第1张图片

最主要的是 QAbstractSocket 类,它是 QUdpSocket 和 QTcpSocket 的父类,QTcpSocket 类又包含了两个子类 QSctpSocket 和 QSslSocket。

二、QUdpSocket 的使用

以下为使用步骤:

  1. 在 pro 或者 pri文件中引入QT 的 network 网络模块:
//修改之前
QT       += core gui
//修改之后
QT       += core gui network
  1. 在文件头部或者头文件中引入 QUdpSocket 模块:
#include
  1. 定义两个 QUdpSocket 指针对象,并初始化:
QUdpSocket* send_udp = new QUdpSocket(this);
QUdpSocket* receive_udp = new QUdpSocket(this);
  1. 使用 udp 协议接收数据,用的 qDebug() 将接收到的数据打印到终端,这里提供两种方式:
    方法一:使用 receiveDatagram() 函数接收数据,接收到的中文数据需要解码,否则为16进制数据(该方法接收到的数据容错率极低,近乎为0)
//设置接收监听地址和端口,这里用的是本机ip
receive_udp -> bind(QHostAddress::LocalHost, 8088);
//绑定监听事件
connect(receive_udp, &QUdpSocket::readyRead, [this](){
	while (receive_udp -> hasPendingDatagrams()) {
		datagram = receive_udp -> receiveDatagram();
		QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");
		qDebug() << utf8 -> toUnicode(datagram.data());
	}
});

方法二:使用 readDatagram() 和 pendingDatagramSize() 函数接收数据,接收到的数据无需解码即可使用(该方法接收到的数据容存在一定的容错率,虽然也能完全接受数据,但是在接收到的数据后方有时存在一些乱码信息)

//设置接收监听地址和端口,这里用的是本机ip
receive_udp -> bind(QHostAddress::LocalHost, 8088);
//绑定监听事件
connect(receive_udp, &QUdpSocket::readyRead, [this](){
	while (receive_udp -> hasPendingDatagrams()) {
		int size = int(receive_udp -> pendingDatagramSize());
		char* pBuffer = new char[size + 1];//分配报文大小的内存
		memset(pBuffer, 0, size + 1);
		receive_udp -> readDatagram(pBuffer, size);
		qDebug() << pBuffer;
	}
});

官方推荐使用用法:

void Server::initSocket() {
    udpSocket = new QUdpSocket(this);
    udpSocket -> bind(QHostAddress::LocalHost, 7755);

    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
}

void Server::readPendingDatagrams() {
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        //这里最好用 long 包含一下udpSocket -> pendingDatagramSize(),否则会有警告
        datagram.resize(udpSocket -> pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        udpSocket -> readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        processTheDatagram(datagram);
    }
}
  1. 使用 udp 协议发送数据:
QString s = "";//字符串的类型可以根据需要自行定义
//writeDatagram(const char * data, qint64 size, const QHostAddress & address, quint16 port)
//该方式发送数据,接收到的中文乱码且解码后少字
send_udp -> writeDatagram(s.toStdString().c_str(), s.length(), QHostAddress::LocalHost, 8088);
//writeDatagram(const QByteArray & datagram, const QHostAddress & host, quint16 port)
//需要发中文,建议使用以下方式
send_udp -> writeDatagram(s.toUtf8(), QHostAddress::LocalHost, 8088);
  1. 这里有一个写好的案例可以参考 BDYSocket.zip通俗易懂玩QT:QUdpSocket学习_第2张图片
    通俗易懂玩QT:QUdpSocket学习_第3张图片

三、注意事项

  1. 监听端口最好使用 1024 以上的,1024 以下的一般都是给系统用的;
  2. 发送中文数据用 QByteArray 类型数据,使用字符数组接收会乱码;
  3. 使用 receiveDatagram() 函数接收中文数据时,需要对数据进行解码,否则出来的是十六进制数据;
  4. 使用 UDP 协议收发数据注意一定要先开启接收监听,然后在发送数据,否则收不到数据的。

学习分享,一起成长!接触QT的时间不长,目前差不多有两个月了,有不足之处,欢迎大佬指出来,我会进行更正。有问题可以发送邮件至 [email protected] ,不定时上线查收。

你可能感兴趣的:(QT学习,qt,socket,qt5,c语言)