文章转自:https://www.cnblogs.com/techiel/p/7978049.html
代码转自:https://blog.csdn.net/we1583004we/article/details/79188305
1. QNetworkDatagram
qt网络报文,可用其建立一个通讯内容包括目标ip、端口号、数据内容。同时接收到的信息也未此类型,可以访问接收数据的长度、发送者的ip及端口等信息
QUdpSocket
有Qt提供的udp通讯的类,详细介绍请见官方文档
2. 客户端
注意pro文件要包含QT += network
- #include <QHostAddress>
- #include <QUdpSocket>
- QUdpSocket *m_socket=new QUdpSocket;
- m_socket.writeDatagram(msg, QHostAddress::localhost, 8000);
qudpsocket对于发送数据报文提供了三个重载函数:
- qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
- qint64 writeDatagram(const QNetworkDatagram &datagram)
- qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
上面的范例使用的是第三种类型,也可以自行建立QNetworkDatagram对象,修改好内容后直接调用writeDatagram
3. 服务端
服务端与客户端类似,需要先绑定端口“bind”,此函数在QAbstractSocket类中提供
- bool bind(const QHostAddress &address, quint16 port = 0, BindMode mode = DefaultForPlatform)
- bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform)
具体使用方式:
- m_socket = new QUdpSocket;
- m_socket->bind(QHostAddress::localhost, 8000);
- connect(m_socket, SIGNAL(readyRead()), this, SLOT(receive()));
绑定端口以后,需要将此socket的readyread信号与自定义槽函数连接,当服务端收到消息时会触发此信号。
4. 消息收发
由于udp与tcp不同,不需要三次握手建立连接,所以并不会在连接之后记录当前socket。
发送消息在客户端中已经提供示例
接收消息需要使用Qudpsocket提供以下函数:
- qint64 pendingDatagramSize() const
- qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)
- QNetworkDatagram receiveDatagram(qint64 maxSize = -1)
当readyRead信号触发时,可直接通过receiveDatagram函数获取消息报文对象,其内存储消息的发送ip、端口、消息内容等所有信息。
也可以通过pendingDatagramSize判断消息长度,然后通过readDatagram获取消息内容。
在readyRead槽函数中可以先调用QUdpSocket::hasPendingDatagrams判断当前是否有需要读取的消息,若有消息再进行pendingDatagramSize获取需要读取的大小
****************************************************************************************************************************************************
客户端
udpclient.cpp
#include "udpclient.h" #include "ui_udpclient.h" #include <QTextCodec> #include <QDebug> UdpClient::UdpClient(QWidget *parent) : QMainWindow(parent), ui(new Ui::UdpClient) { ui->setupUi(this); //QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); clientudp=new QUdpSocket(this); clientudp->bind(6000,QUdpSocket::ShareAddress);//绑定读数据端口(监听端口),允许其他服务绑定到此端口 connect(clientudp,SIGNAL(readyRead()),this,SLOT(recv())); } UdpClient::~UdpClient() { delete ui; } void UdpClient::on_pushButton_clicked() { // QHostAddress serverip; // serverip.setAddress(QString("192.168.0.7"));//这是人为指定ip地址的方法 clientudp->writeDatagram(QVariant(ui->textEdit_write->toPlainText()).toByteArray(),QHostAddress::LocalHost,5000);//向5000端口写数据 } void UdpClient::recv() { while(clientudp->hasPendingDatagrams()) { QByteArray data; data.resize(clientudp->pendingDatagramSize()); clientudp->readDatagram(data.data(),data.size()); ui->textEdit_show->setText(QVariant(data).toString()); } } //注意,监听与发送的端口可以相同也可以不同,它们相对独立,就像有名管道
服务端代码:
udpserver.cpp
#include "udpserver.h" #include "ui_udpserver.h" #include <QVariant> UdpServer::UdpServer(QWidget *parent) : QMainWindow(parent), ui(new Ui::UdpServer) { ui->setupUi(this); serverudp=new QUdpSocket(this); serverudp->bind(5000,QUdpSocket::ShareAddress);//绑定读数据端口(监听端口),允许其他服务绑定到此端口 connect(serverudp,SIGNAL(readyRead()),this,SLOT(recv())); } UdpServer::~UdpServer() { delete ui; } void UdpServer::recv() { while(serverudp->hasPendingDatagrams()) { QByteArray data; data.resize(serverudp->pendingDatagramSize()); serverudp->readDatagram(data.data(),data.size());// ui->textEdit_show->clear(); ui->textEdit_show->setText(QVariant(data).toString()); } } void UdpServer::on_pushButton_clicked() { // QHostAddress serverip; // serverip.setAddress(QString("192.168.0.7"));//这是人为指定ip地址的方法 serverudp->writeDatagram(QVariant(ui->textEdit_write->toPlainText()).toByteArray(),QHostAddress::LocalHost,6000);//向6000端口写数据 } //注意,监听与发送的端口可以相同也可以不同,它们相对独立,就像有名管道