UDP(用户数据报协议),是一个轻量的,不可靠的,面向数据报的,非连接的协议。当通讯要求的可靠性不重要时(可能数据会丢失),可以用UDP通信
.pro文件中添加网络模块 QT += network 头文件:#include<QUdpSocket> 重要函数:
bind()
hasPendingDatagrams()
writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)
pendingDatagramSize()
joinMulticastGroup()
leaveMulticastGroup()
设计一下UI: 服务器: 1.绑定端口
m_udpSocket->bind(QHostAddress::AnyIPv4,8888);
2.发送消息 和 读取消息 2.1发送消息
QString sendStr = ui.sendTextEdit->toPlainText();
quint16 port = ui.portLineEdit->text().toInt();
QString ip = ui.IPlineEdit->text();
m_udpSocket->writeDatagram(sendStr.toUtf8(), QHostAddress(ip), port);
connect(m_udpSocket, &QUdpSocket::readyRead, this, &QUdpTest::readValue);
2.2读取消息
while (m_udpSocket->hasPendingDatagrams())
{
QByteArray array;
array.resize(m_udpSocket->pendingDatagramSize());
QHostAddress address;
quint16 port;
m_udpSocket->readDatagram(array.data(), array.size(),&address,&port);
qDebug() << QStringLiteral("传过来的大小为:") << array.size();
qDebug() << array.data();
Person* p = reinterpret_cast<Person*>(array.data());
QString str1 = QString(QLatin1String(p->name));
QString str = QString("%1 %2 %3").arg(QString::number(p->age)).arg(str1).arg(QString::number(p->score));
ui.recvTextEdit->setText(str);
}
客户端: 1.绑定端口
m_socket->bind(QHostAddress::AnyIPv4,9999);
2.发送消息 和 读取消息 2.1发送消息
quint16 port = ui.portLineEdit->text().toInt();
QString ip = ui.IPLineEdit->text();
QString sendStr = ui.sendTextEdit->toPlainText();
Person p1;
strcpy(p1.name, "xm");
p1.age = 20;
p1.score = 60;
m_socket->writeDatagram(( char*)&p1, sizeof(Person), QHostAddress(ip), port);
qDebug() << QStringLiteral("发送的数据大小:") << sizeof(p1);
2.2读取消息
while (m_socket->hasPendingDatagrams())
{
QByteArray array;
array.resize(m_socket->pendingDatagramSize());
QHostAddress address;
quint16 port;
m_socket->readDatagram(array.data(), array.size(), &address, &port);
ui.recvTextEdit->setText(array);
}
3.客户端和服务端都加入组播 UDP组播是主机间一对一组的通信模式,当多个客户端加入由一个组播地址定义的多播组后,客户端向这个组播地址和端口发送的UDP数据报,组内成员都可以接收到。
m_socket->joinMulticastGroup(QHostAddress("224.0.0.100"));
完整代码: QUdpTest.h
#pragma once
#include <QtWidgets/QWidget>
#include "ui_QUdpTest.h"
#include <QUdpSocket>
#include <QDebug>
class QUdpTest : public QWidget
{
Q_OBJECT
struct Person
{
char name[20];
int age;
int score;
Person()
{
memset(name, 0, 20);
age = 0;
score = 0;
}
};
public:
QUdpTest(QWidget *parent = Q_NULLPTR);
~QUdpTest();
public slots:
void readValue();
void on_sendBtn_clicked();
void on_delBtn_clicked();
private:
Ui::QUdpTestClass ui;
QUdpSocket* m_udpSocket;
};
QUdpTest.cpp
#include "QUdpTest.h"
#include <QDebug>
#include <QByteArray>
#include <QString>
#include <QLatin1String>
QUdpTest::QUdpTest(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_udpSocket = new QUdpSocket(this);
this->setWindowTitle(QStringLiteral("绑定端口号为:8888"));
m_udpSocket->bind(QHostAddress::AnyIPv4,8888);
m_udpSocket->joinMulticastGroup(QHostAddress("224.0.0.100"));
connect(m_udpSocket, &QUdpSocket::readyRead, this, &QUdpTest::readValue);
ui.recvTextEdit->setReadOnly(true);
}
QUdpTest::~QUdpTest()
{
}
void QUdpTest::readValue()
{
while (m_udpSocket->hasPendingDatagrams())
{
QByteArray array;
array.resize(m_udpSocket->pendingDatagramSize());
QHostAddress address;
quint16 port;
m_udpSocket->readDatagram(array.data(), array.size(),&address,&port);
qDebug() << QStringLiteral("传过来的大小为:") << array.size();
qDebug() << array.data();
Person* p = reinterpret_cast<Person*>(array.data());
QString str1 = QString(QLatin1String(p->name));
QString str = QString("%1 %2 %3").arg(QString::number(p->age)).arg(str1).arg(QString::number(p->score));
ui.recvTextEdit->setText(str);
}
}
void QUdpTest::on_sendBtn_clicked()
{
QString sendStr = ui.sendTextEdit->toPlainText();
quint16 port = ui.portLineEdit->text().toInt();
QString ip = ui.IPlineEdit->text();
m_udpSocket->writeDatagram(sendStr.toUtf8(), QHostAddress(ip), port);
}
void QUdpTest::on_delBtn_clicked()
{
m_udpSocket->leaveMulticastGroup(QHostAddress("224.0.0.100"));
}
QUdpTest1.h
#pragma once
#include <QWidget>
#include "ui_QUdpTest1.h"
#include <QUdpSocket>
class QUdpTest1 : public QWidget
{
Q_OBJECT
struct Person
{
char name[20];
int age;
int score;
Person()
{
memset(name, 0, 20);
age = 0;
score = 0;
}
};
public:
QUdpTest1(QWidget *parent = Q_NULLPTR);
~QUdpTest1();
public slots:
void readValue();
void on_sendBtn_clicked();
void on_delBtn_clicked();
private:
Ui::QUdpTest1 ui;
QUdpSocket* m_socket;
};
QUdpTest1.cpp
#include "QUdpTest1.h"
#include <string.h>
QUdpTest1::QUdpTest1(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_socket = new QUdpSocket(this);
this->setWindowTitle(QStringLiteral("绑定端口为:9999"));
m_socket->bind(QHostAddress::AnyIPv4,9999);
m_socket->joinMulticastGroup(QHostAddress("224.0.0.100"));
connect(m_socket, &QUdpSocket::readyRead, this, &QUdpTest1::readValue);
ui.recvTextEdit->setReadOnly(true);
}
QUdpTest1::~QUdpTest1()
{
}
void QUdpTest1::readValue()
{
while (m_socket->hasPendingDatagrams())
{
QByteArray array;
array.resize(m_socket->pendingDatagramSize());
QHostAddress address;
quint16 port;
m_socket->readDatagram(array.data(), array.size(), &address, &port);
ui.recvTextEdit->setText(array);
}
}
void QUdpTest1::on_sendBtn_clicked()
{
quint16 port = ui.portLineEdit->text().toInt();
QString ip = ui.IPLineEdit->text();
QString sendStr = ui.sendTextEdit->toPlainText();
Person p1;
strcpy(p1.name, "xm");
p1.age = 20;
p1.score = 60;
m_socket->writeDatagram(( char*)&p1, sizeof(Person), QHostAddress(ip), port);
qDebug() << QStringLiteral("发送的数据大小:") << sizeof(p1);
}
void QUdpTest1::on_delBtn_clicked()
{
m_socket->leaveMulticastGroup(QHostAddress("224.0.0.100"));
}
运行结果: 发送文本中的内容: 发送结构体中的内容: 参考博客: QT网络编程之UDP
|