一、准备
(一)开发环境
系统:Windows 7 专业版(64位)
软件:qt-opensource-windows-x86-mingw530-5.7.0(原来用Qt 5.2.1+完成的工程)
注:Qt下载链接http://download.qt.io/official_releases/qt/
(二)知识准备
Qt 5入门请看书籍《C++ Qt5 范例开发大全 》(可通过网络搜索,也可以通过Qt交流QQ群获得)。
Qt创建工程请看百度教程:http://jingyan.baidu.com/article/7908e85c95d538af491ad274.html
网络传输协议知识,请自行脑补!
二、开发过程
(一)创建Qt 工程,命名udpEndpoint1(任何名字都可以,只要符合Qt文件命名规则)
创建没有严格按照步骤一步步来,就点一下关键的地方。
1. 选择QWidget基类
2. 创建完成
(二)打开udpEndpoint1.pro,找到代码行,就在正文第一行
QT += core gui
右边加上“network”,这一步非常重要,这样才能加载Qt中与网络有关的库(这是我自己的理解,不专业),不然后面程序运行会报错。修改如下:
QT += core gui network
注:请注意一下.pro的内容和工程文件中头文件和源文件下的文件,后文中会用到。
(三)创建一个新类(类名:udpSender)
创建类的步骤:
1. 点击:文件 --> 新建文件或项目,进入界面如下
2. 选择:文件和类 --> C++
3. 选择C++ Class,进入界面如下图
4. 类名:udpSender,基类(Base Class):QObject,类存放路径一定要保证存在main.c所在的路径下(之前我创建在其他路径,工程文件里不出现类定义文件:.cpp和.h)
5.一路“下一步”,直到完成
头文件里就多了个udpsender.h,源文件里也多了个udpsender.cpp。再看.pro文件内容,SOURCES下面多了一个udpsender.cpp;HEADERS,下面也多了个udpsender.h
SOURCES += main.cpp\
widget.cpp \
udpsender.cpp
HEADERS += widget.h \
udpsender.h
(四)定义类文件
1.打开udpsender.h,修改代码为:
//udpsender.h
#ifndef UDPSENDER_H
#define UDPSENDER_H
#include <QObject>
#include <QtNetwork/QUdpSocket>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QHostInfo>
class udpSender : public QObject
{
Q_OBJECT
public:
explicit udpSender(QObject *parent = 0);
udpSender(QString recv_host,quint16 recv_port,quint16 port);
~udpSender();
void setReceiverHost(QString host);//设置接收端的socket地址
void setReceiverPort(quint16 port);//设置接收端的socket端口
void setReceiverAddress(QString host,quint16 port); //设置接收端的socket地址和端口
void setSenderPort(quint16 port); //设置发送端socket端口
void udpSocketBindUpdate(); //更新socket绑定的端口号,端口号就是设置的发送端socket端口
void sendDatagram(QByteArray datagram); //数据发送
private:
QUdpSocket *udpSocket; //socket对象
QHostAddress *receiver_host; //接收端的IP地址
quint16 sender_port,receiver_port; //发送端端口,接收端端口
signals:
public slots:
};
#endif // UDPSENDER_H
2.打开udpsender.cpp,修改代码
//udpsender.cpp
#include "udpsender.h"
udpSender::udpSender(QObject *parent) :
QObject(parent)
{
udpSocket = new QUdpSocket(this);
receiver_host = new QHostAddress("127.0.0.1");
receiver_port = -1;
sender_port = -1;
}
udpSender::udpSender(QString recv_host,quint16 recv_port,quint16 port)
{
udpSocket = new QUdpSocket(this);
receiver_host = new QHostAddress(recv_host);
receiver_port = recv_port;
sender_port = port;
}
void udpSender::setReceiverHost(QString host)
{
receiver_host->setAddress(host);
}
void udpSender::setReceiverPort(quint16 port)
{
receiver_port = port;
}
void udpSender::setReceiverAddress(QString host,quint16 port)
{
setReceiverHost(host);
setReceiverPort(port);
}
void udpSender::setSenderPort(quint16 port)
{
sender_port = port;
}
void udpSender::udpSocketBindUpdate()
{
udpSocket->abort();
udpSocket->bind(sender_port);
}
void udpSender::sendDatagram(QByteArray datagram)
{
udpSocket->writeDatagram(datagram,*receiver_host,receiver_port);
}
udpSender::~udpSender()
{
udpSocket->close();
}
到此,类文件定义完毕!
(五)ui设计
打开界面文件widget.ui,设计如下界面
控件的属性如下:
控件标记 | 控件类型 | 控件名称(objectName) |
1 | QLineEdit | dest_ip |
2 | QLineEdit | dest_port |
3 | QLineEdit | lineEdit |
4 | QTextEdit | textEdit |
目标IP地址、目标端口 | QLabel | * |
指定发送端口、发送数据 | QLabel | * |
发送 | QPushButton | pushButton |
清空 | QPushButton | pushButton_2 |
ui界面设置信号和槽:
pushButton_2,也就是“清空”按钮,产生信号click(),连接到textEdit,也就是编号为4的编辑框,槽函数为clear()。
(六)编辑Widget代码
1. 打开widge.h,编辑如下:
//widge.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <udpsender.h>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
udpSender *sender;
explicit Widget(QWidget *parent = 0);
~Widget();
quint16 getRecvPortInput(); //接收编辑框输入-->接收端socket端口
QString getRecvHostInput(); //接收编辑框输入-->接收端socket地址
quint16 getSendPortInput(); //接收编辑框输入-->发送端socket端口
QByteArray getDataInput(); //获取待发送数据输入
public slots:
void on_pushButton_clicked(); //发送按钮槽函数
private:
Ui::Widget *ui;
};
2. 打开widge.cpp,编辑代码如下:
//widge.cpp
#include "widget.h"
#include "ui_widget.h"
#include "QtNetwork"
#include "QMessageBox"
QRegExp regExpIP("((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[\\.]){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])");
QRegExp regExpNetPort("((6553[0-5])|[655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])");
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("UDP发送端");
ui->dest_port->setValidator\
(new QRegExpValidator(regExpNetPort,this));
ui->lineEdit->setValidator\
(new QRegExpValidator(regExpNetPort,this));
ui->dest_ip->setValidator(new QRegExpValidator(regExpIP,this));
sender = new udpSender();
}
QString Widget::getRecvHostInput()
{
return ui->dest_ip->text();
}
quint16 Widget::getRecvPortInput()
{
quint16 dest_port;
QString inputDestPort = ui->dest_port->text();
if(inputDestPort.isEmpty())
dest_port = -1;
else
//QString 文本输入,转换为quint16的数字端口
dest_port = inputDestPort.toUInt();
return dest_port;
}
//指定发送端口
quint16 Widget::getSendPortInput()
{
quint16 sourcePort;
QString inputSourcePort = ui->lineEdit->text();
if(inputSourcePort.isEmpty())
sourcePort = -1;
else
//QString 文本输入,转换为quint16的数字端口
sourcePort = inputSourcePort.toUInt();
return sourcePort;
}
QByteArray Widget::getDataInput()
{
//处理文本输入
QString text = ui->textEdit->toPlainText();
QByteArray datagram = text.toUtf8(); //中文编码
return datagram;
}
Widget::~Widget()
{
delete ui;
}
//发送
void Widget::on_pushButton_clicked()
{
sender->setSenderPort(getSendPortInput());
sender->setReceiverHost(getRecvHostInput());
sender->setReceiverPort(getRecvPortInput());
sender->udpSocketBindUpdate();
sender->sendDatagram(getDataInput());
}
main.cpp的代码不用修改,为了方便科友查看,也把它放出来。
//main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
(七)运行程序
点击运行按钮,运行结果如下:
实例:
我要用本机的udp socket的8082口发送数据到另一台主机(IP: 10.106.10.203,PORT:8083),发送数据为:Hello,很高兴认识你。
输入界面如下:
到此为止,udp发送端的程序开发已经完成,udp接收端将在后续的博客中再谈。
此帖重在交流,如有问题,请QQ联系:1592017939,水平有限,请多指正!
来源:oschina
链接:https://my.oschina.net/u/2936888/blog/803803