udp通信分为发送端和接收端,通信步骤可以分为以下:
接收端:
- 创建QUdpSocket对象。在.h文件中添加类的前置声明,定义该类的指针,在.cpp的构造函数中定义指向该类的指针。
- bind()。绑定IP和端口。
- connect()。绑定readyRead()信号,当有数据到来的时候,触发这个信号,在对应的槽函数中处理数据,读数据调用readDatagram()函数,在第三,四个参数可以保存发送端的IP和端口。
发送端:
1.创建QUdpSocket对象。在.h文件中添加类的前置声明,定义该类的指针,在.cpp的构造函数中定义指向该类的指针。
2.发送数据。调用writeDatagram()函数发送数据到指定的IP和端口。
下面是界面效果:
发送端的代码:
Send.h
#ifndef SEND_H
#define SEND_H#include <QDialog>QT_BEGIN_NAMESPACE
namespace Ui { class Send; }
QT_END_NAMESPACEclass QUdpSocket;class Send : public QDialog
{Q_OBJECTpublic:Send(QWidget *parent = nullptr);~Send();private slots:void on_textEdit_cursorPositionChanged();void on_sendButton_clicked();private:Ui::Send *ui;QUdpSocket *sender;
};
#endif // DIALOG_H
Send.cpp
#include "Send.h"
#include "ui_Send.h"
#include <QtNetwork>
#include <QDebug>Send::Send(QWidget *parent): QDialog(parent), ui(new Ui::Send)
{ui->setupUi(this);setWindowTitle(tr("发送端"));sender = new QUdpSocket(this);ui->sendButton->setEnabled(false);
}Send::~Send()
{delete ui;
}void Send::on_textEdit_cursorPositionChanged()
{if(!ui->textEdit->toPlainText().isEmpty()){ui->sendButton->setEnabled(true);}
}void Send::on_sendButton_clicked()
{QByteArray text = ui->textEdit->toPlainText().toUtf8();//每次只发送输入的哪些文字,不会追加qint64 bytes = sender->writeDatagram(text,text.size(),QHostAddress::LocalHost,7777);if(bytes == -1){qDebug()<<"发送数据失败!";return ;}
}
接收端的代码:
Receive.h
#ifndef RECEIVE_H
#define RECEIVE_H#include <QDialog>QT_BEGIN_NAMESPACE
namespace Ui { class Receive; }
QT_END_NAMESPACEclass QUdpSocket;
class QTimer;class Receive : public QDialog
{Q_OBJECTpublic:Receive(QWidget *parent = nullptr);~Receive();
private slots:void slot_readyRead();void slot_error();void slot_timeout();
private:Ui::Receive *ui;QUdpSocket *receiver;QTimer *timer;
};
#endif // RECEIVE_H
Receive.cpp
#include "receive.h"
#include "ui_receive.h"
#include <QtNetwork>
#include <QDebug>
#include <QTimer>Receive::Receive(QWidget *parent): QDialog(parent), ui(new Ui::Receive)
{ui->setupUi(this);setWindowTitle(tr("接收端"));receiver = new QUdpSocket(this);receiver->bind(QHostAddress("127.0.0.1"),7777);connect(receiver,&QUdpSocket::readyRead,this,&Receive::slot_readyRead);timer = new QTimer(this);connect(timer,&QTimer::timeout,this,&Receive::slot_timeout);
// void (QUdpSocket:: *errorSign)(QAbstractSocket::SocketError) = &QUdpSocket::error;
// connect(receiver,errorSign,this,&Receive::slot_error);//用不上error信号,发送端与接收端是无连接的,给关闭发送端,//对于接收端没有联动的影响
}Receive::~Receive()
{delete ui;
}void Receive::slot_readyRead()
{if(receiver->hasPendingDatagrams()){QHostAddress sendAddr;//发送者的IP地址quint16 port;//发送者的端口QByteArray text;text.resize(receiver->pendingDatagramSize());receiver->readDatagram(text.data(),(qint64)text.size(),&sendAddr,&port);qDebug()<<sendAddr.toString()<<port;//输出发送端的IP和端口号,(端口号还不是和能理解,为什么不是7777)ui->textEdit->setPlainText(text);//会自动在上一次的内容后面追加ui->label->setText(tr("数据接收完成!"));timer->start(2000);}
}void Receive::slot_error()
{qDebug()<<receiver->errorString();receiver->close();
}void Receive::slot_timeout()
{ui->label->setText(tr(" "));
}
以上是UDP通信时,发送端与接收端的代码,其main.cpp文件没有任何的改变,所以没有贴,由于Udp是无连接的,所以最后关于close()套接字,一般没有用到,因为发送完消息之后,调用close()来关闭套接字和没有调用close()关闭套接字的效果是一样的,他们之间没有连接,只是在传输数据时指定了端口与IP,当然很多东西还没有接触到具体视情况而定close()的有无。