本机运行两个实例需要绑定不同的端口,例如实例A绑定端口2000,实例B绑定端口3000,实例A向实例B发送数据时,需要指定实例B所在主机的IP地址、绑定端口作为目标地址和目标端口,这样实例B才能接收到数据报。如果在不同的计算机运行,则可以使用相同的端口。
要实现数据接收,必须先使用QUdpSocket::bind()绑定一个端口,用于监听传入的数据报。解除绑定则使用abort()函数。
writeDatagram()函数向一个目标用户发送消息时,需要指定目标地址和端口。
在广播消息时,只需要将目标地址更换为一个特殊地址,即广播地址QHostAddress::Broadcast,一般为255.255.255.255
发送的数据报是QByteArray类型的字节数组,数据报的长度一般不超过512字节,可以是文本,也可以是二进制数据。
接收到数据报后会发射readyRead()信号。
#ifndef WIDGET_H
#define WIDGET_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_btnBind_clicked();
void on_btnUnBind_clicked();
void on_btnClear_clicked();
void on_btnQuit_clicked();
void on_btnSend_clicked();
void on_btnBroadcast_clicked();
void on_readyRead();
private:
Ui::Widget *ui;
private:
QUdpSocket *m_udpSocket = nullptr;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QHostInfo>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//本地主机名
QString hostName = QHostInfo::localHostName();
//本机IP地址
QHostInfo hostInfo = QHostInfo::fromName(hostName);
//IP地址列表
QList<QHostAddress> addrList = hostInfo.addresses();
for(int i=0;i<addrList.count();i++)
{
QHostAddress host = addrList.at(i);
if(QAbstractSocket::IPv4Protocol == host.protocol())
{
QString ip = host.toString();
ui->comboBox->addItem(ip);
}
}
m_udpSocket = new QUdpSocket(this);
connect(m_udpSocket,&QUdpSocket::readyRead,this,&Widget::on_readyRead);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnBind_clicked()
{
//本机UDP端口
qint16 port = ui->spinBindPort->value();
if(m_udpSocket->bind(port))
{
ui->plainTextEdit->appendPlainText("**已成功绑定");
ui->plainTextEdit->appendPlainText("**绑定端口: "+QString::number(m_udpSocket->localPort()));
ui->btnBind->setEnabled(false);
ui->btnUnBind->setEnabled(true);
}
else
{
ui->plainTextEdit->appendPlainText("**绑定失败");
}
}
void Widget::on_btnUnBind_clicked()
{
//解除绑定
m_udpSocket->abort();
ui->btnBind->setEnabled(true);
ui->btnUnBind->setEnabled(false);
ui->plainTextEdit->appendPlainText("**已解除绑定");
}
void Widget::on_btnClear_clicked()
{
ui->plainTextEdit->clear();
}
void Widget::on_btnQuit_clicked()
{
}
void Widget::on_btnSend_clicked()//单播
{
//目标IP
QString dstIp = ui->comboBox->currentText();
QHostAddress dstAddr(dstIp);
//目标端口
quint16 dstPort = ui->spinDstPort->value();
QString msg = ui->lineEdit->text();
QByteArray str = msg.toUtf8();
//发出数据报
m_udpSocket->writeDatagram(str,dstAddr,dstPort);
ui->plainTextEdit->appendPlainText("[out] "+msg);
}
void Widget::on_btnBroadcast_clicked()//广播
{
quint16 dstPort = ui->spinDstPort->value();
QString msg = ui->lineEdit->text();
QByteArray str = msg.toUtf8();
//发出数据报
m_udpSocket->writeDatagram(str,QHostAddress::Broadcast,dstPort);
ui->plainTextEdit->appendPlainText("[Broadcast] "+msg);
}
void Widget::on_readyRead()
{
//是否还有待读取的传入数据报
while(m_udpSocket->hasPendingDatagrams())
{
QByteArray data;
//返回待读取的数据报的字节数
data.resize(m_udpSocket->pendingDatagramSize());
QHostAddress peerAddr;
quint16 peerPort;
//读取数据报的内容
m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);
QString str = data.data();
QString peer = "[From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";
ui->plainTextEdit->appendPlainText(peer+str);
}
}
原文链接:https://blog.csdn.net/wzz953200463/article/details/115101133