Qt5基于UDP的网络广播程序以及中文乱码问题

UDP服务端界面(发送端)
在这里插入图片描述
UDP客户端(接收端)
在这里插入图片描述

UDP服务端

(1)在头文件“udpserver.h”中声明了需要的各种控件,其具体代码如下:

#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
class UdpServer : public QDialog
{
    Q_OBJECT
public:
    UdpServer(QWidget *parent=0,Qt::WindowFlags f=0);
    ~UdpServer();
private:
    QLabel *TimerLabel;
    QLineEdit *TextLineEdit;
    QPushButton *StartBtn;
    QVBoxLayout *mainLayout;
};

(2)源文件“udpserver.cpp”的具体代码如下:

#include "udpserver.h"
UdpServer::UdpServer(QWidget *parent,Qt::WindowFlags f)
    : QDialog(parent,f)
{
    setWindowTitle(tr("UDP Server"));			//设置窗体的标题
	/* 初始化各个控件 */
    TimerLabel = new QLabel(tr("计时器:"),this);
    TextLineEdit = new QLineEdit(this);
    StartBtn = new QPushButton(tr("开始"),this);
	/* 设置布局 */
    mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(TimerLabel);
    mainLayout->addWidget(TextLineEdit);
    mainLayout->addWidget(StartBtn);
}

UDP服务器具体操作步骤如下。
(1)在“UdpServer.pro”中添加如下语句:

QT += network

(2)在头文件“udpserver.h”中添加需要的槽函数,其具体代码如下:

#include <QUdpSocket>
#include <QTimer>
public slots:
    	void StartBtnClicked();
    	void timeout();
private:
	int port;
    	bool isStarted;
    	QUdpSocket *udpSocket;
    	QTimer *timer;

(3)在源文件“udpserver.cpp”中添加声明:

#include

其中,在构造函数中添加如下代码:

connect(StartBtn,SIGNAL(clicked()),this,SLOT(StartBtnClicked()));
port = 5555;				//设置UDP的端口号参数,服务器定时向此端口发送广播信息
isStarted = false;
udpSocket = new QUdpSocket(this);
timer = new QTimer(this);	//创建一个QUdpSocket
//定时发送广播信息
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));

StartBtnClicked()函数的具体代码如下:

void UdpServer::StartBtnClicked()
{
    if(!isStarted)
    {
        StartBtn->setText(tr("停止"));
        timer->start(1000);
        isStarted =true;
    }
    else
    {
        StartBtn->setText(tr("开始"));
        isStarted = false;
        timer->stop();
    }
}

timeout()函数完成了向端口发送广播信息的功能,其具体代码如下:

void UdpServer::timeout()
{
    QString msg = TextLineEdit->text();
    int length=0;
    if(msg=="")
    {
       return;
    }
    if((length=udpSocket->writeDatagram(msg.toLatin1(),
    msg.length(),QHostAddress::Broadcast,port))!=msg.length())
    {
        return;
    }
}

UDP客户端编程

(1)在头文件“udpclient.h”中声明了需要的各种控件,其具体代码如下:

#include <QDialog>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QPushButton>
class UdpClient : public QDialog
{
    Q_OBJECT
public:
    UdpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~UdpClient();
private:
    QTextEdit *ReceiveTextEdit;
    QPushButton *CloseBtn;
    QVBoxLayout *mainLayout;
};

(2)源文件“udpclient.cpp”的具体代码如下:

#include "udpclient.h"
UdpClient::UdpClient(QWidget *parent, Qt::WindowFlags f)
    : QDialog(parent,f)
{
    setWindowTitle(tr("UDP Client"));		//设置窗体的标题
	/* 初始化各个控件 */
    ReceiveTextEdit = new QTextEdit(this);
    CloseBtn = new QPushButton(tr("Close"),this);
	/* 设置布局 */
    mainLayout=new QVBoxLayout(this);
    mainLayout->addWidget(ReceiveTextEdit);
    mainLayout->addWidget(CloseBtn);
}

以上只是完成了客户端界面的实现,下面完成它的数据接收和显示的功能。
操作步骤如下。
(1)在“UdpClient.pro”中添加如下语句:

QT += network

(2)在头文件“udpclient.h”中添加如下代码:

#include <QUdpSocket>
public slots:
    	void CloseBtnClicked();
    	void dataReceived();
private:
	int port;
    	QUdpSocket *udpSocket;

(3)在源文件“udpclient.cpp”中添加如下声明:

#include <QMessageBox>
#include <QHostAddress>

其中,在构造函数中添加的代码如下:

connect(CloseBtn,SIGNAL(clicked()),this,SLOT(CloseBtnClicked()));
port =5555;			//设置UDP的端口号参数,指定在此端口上监听数据
udpSocket = new QUdpSocket(this);		//创建一个QUdpSocket
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));	//(a)
bool result=udpSocket->bind(port);		//绑定到指定的端口上
if(!result)
{
    QMessageBox::information(this,tr("error"),tr("udp socket create error!"));
    return;
}

CloseBtnClicked()函数的具体内容如下:

void UdpClient::CloseBtnClicked()
{
    close();
}

dataReceived()函数响应QUdpSocket的readyRead()信号,一旦UdpSocket对象中有数据可读时,即通过readDatagram()方法将数据读出并显示。其具体代码如下:

void UdpClient::dataReceived()
{
    while(udpSocket->hasPendingDatagrams())			//(a)
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());	//(b)
        QString msg=datagram.data();
        ReceiveTextEdit->insertPlainText(msg);			//显示数据内容
    }
}

同时运行UdpServer与UdpClient工程,首先在服务器界面的文本框中输入“hello!”,然后单击“开始”按钮,按钮文本变为“停止”,客户端就开始不断地收到“hello!”字符消息并显示在文本区,当单击服务器的“停止”按钮后,按钮文本又变回“开始”,客户端也就停止了字符的显示,再次单击服务器的“开始”按钮,客户端又继续接收并显示……如此循环往复。
在这里插入图片描述
但是如果传送的信息是中文,则会出现一段问号:
在这里插入图片描述

中文乱码的解决办法

  • 发送端将要发送的字符串转成UTF-8的格式
  • 接收端将UTF-8的数据转成字符串

发送端

写报文的函数原型:

qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port) //(1)
qint64 writeDatagram(const QNetworkDatagram &datagram)//(2)
qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)//(3)

在使用第一个函数原型时,要特别注意size是编码后数据的长度,也就是data的长度,而不是原始数据的长度。

将原始的写报文代码:

    if((length=udpSocket->writeDatagram(msg.toLatin1(),
    msg.length(),QHostAddress::Broadcast,port))!=msg.length())
    {
        return;
    }

改成

    if(
    (length = udpSocket->writeDatagram (msg.toUtf8 ().data(), msg.toUtf8().size(),
    QHostAddress::Broadcast,port))!= msg.length ()
            )
    {
        return ;
    }

使用第三个函数原型:

  /*发送数据
     * 第一个参数:要发送的内容,这里是要发送输入框的内容,
     * 参数没有QString类型,需要转换为QByteArray类型或Char*类型
     * 第二个参数:要发送到的目标IP地址,这里是本机测试,所以用LocalHost
     * 第三个参数:要发送的的目标端口,自己随意指定
     * 返回值:发送成功返回发送的字节数,失败返回-1
     */
qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)

将原始的写报文代码改成:

    if((length =
        udpSocket->writeDatagram (msg.toUtf8 (),QHostAddress::Broadcast,port))
            != msg.length ())
    {
        return ;
    }

接收端

读报文的函数原型:

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

将读报文的代码:

        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());	//(b)
        QString msg=datagram.data();
        ReceiveTextEdit->insertPlainText(msg);			//显示数据内容

改成:

        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());	//(b)
        //将utf-8的数据转成字符串
        QString msg=QString::fromUtf8 (datagram.data ());
        ReceiveTextEdit->insertPlainText(msg);			//显示数据内容

最后效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值