Qt4_发送和接收UDP数据报
发送和接收UDP数据报
QUdpSocket类可以用来发送和接收UDP数据报(datagram)。UDP是一种不可靠的,面向数据报的协议。一些应用层的协议使用UDP,因为它比TCP更加小巧轻便。采用UDP,数据是以包(数据报)的形式从一个主机发送到另一个主机的。这里并没有连接的概念,而且如果UDP包没有被成功投递,它不会向发送者报告任何错误。
我们将会通过Weather Balloon和Weather Station 这两个实例来看看在Qt应用程序中是如何使用UDP的。Weather Balloon应用程序模拟气象气球的功能,每2秒钟就发送个包含当前天气情况的UDP数据报(假设使用无线连接)。
class WeatherBalloon : public QPushButton
{Q_OBJECTpublic:WeatherBalloon(QWidget *parent = 0);double temperature() const;double humidity() const;double altitude() const;private slots:void sendDatagram();private:QUdpSocket udpSocket;QTimer timer;
};
WeatherBalloon类派生自QPushButton。它借助QPushButton的QUdpSocket私有变量与WeatherStation进行通信。
WeatherBalloon::WeatherBalloon(QWidget *parent): QPushButton(tr("Quit"), parent)
{connect(this, SIGNAL(clicked()), this, SLOT(close()));connect(&timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));timer.start(2 * 1000);setWindowTitle(tr("Weather Balloon"));
}
在构造函数中,利用一个QTimer来实现每2秒钟调用一次sendDatagram()。
void WeatherBalloon::sendDatagram()
{QByteArray datagram;QDataStream out(&datagram, QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_4_3);out << QDateTime::currentDateTime() << temperature() << humidity()<< altitude();udpSocket.writeDatagram(datagram, QHostAddress::LocalHost, 5824);
}
在sendDatagram()中,生成并发送一个包含当前日期、时间、温度、湿度和高度的数据报:
这个数据报是利用QUdpSocket::writeDatagram()发送的。writeDatagram()的第二个和第三个参数是IP 地址和另一端的端口号(Weather Station)。 对于这个实例,我们假设Weather Station 和Weather Balloon 运行在同一台机器上,所以使用127.0.0.1(QHostAddress::LocalHost)的IP地址,它是指定本地主机的特殊地址。
与QTcpSocket::connectToHost()不同,QUdpSocket::writeDatagram()不接受主机名称,而只能使用主机地址。如果想在这里把主机名称解析成为它的IP地址,有两种选择:在查找发生时阻塞,然后使用QHostnfo::fromNamne()静态函数;或者,使用QHostUnfo::lookupHost()静态函数。当查找完成时,它将立即返回,同时利用含有相应地址的:QHostInfo对象传递而调用槽。
int main(int argc, char *argv[])
{QApplication app(argc, argv);WeatherBalloon balloon;balloon.show();return app.exec();
}
main()函数仅仅创建了一个WeatherBalloon对象,它既作为一个UDP端进行服务,也作为一个QPushButton显示在屏幕上。单击QPushButton,就可以退出应用程序。现在看一下WeatherStation客户端的源代码:
weatherballon.h
#ifndef WEATHERBALLOON_H
#define WEATHERBALLOON_H#include <QPushButton>
#include <QTimer>
#include <QUdpSocket>class WeatherBalloon : public QPushButton
{Q_OBJECTpublic:WeatherBalloon(QWidget *parent = 0);double temperature() const;double humidity() const;double altitude() const;private slots:void sendDatagram();private:QUdpSocket udpSocket;QTimer timer;
};#endif
weatherballon.cpp
#include <QtCore>
#include <QtNetwork>
#include <cstdlib>#include "weatherballoon.h"WeatherBalloon::WeatherBalloon(QWidget *parent): QPushButton(tr("Quit"), parent)
{connect(this, SIGNAL(clicked()), this, SLOT(close()));connect(&timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));timer.start(2 * 1000);setWindowTitle(tr("Weather Balloon"));
}double WeatherBalloon::temperature() const
{return -20.0 + (2.0 * std::rand() / (RAND_MAX + 1.0));
}double WeatherBalloon::humidity() const
{return 20.0 + (2.0 * std::rand() / (RAND_MAX + 1.0));
}double WeatherBalloon::altitude() const
{return 7000 + (100.0 * std::rand() / (RAND_MAX + 1.0));
}void WeatherBalloon::sendDatagram()
{QByteArray datagram;QDataStream out(&datagram, QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_4_3);out << QDateTime::currentDateTime() << temperature() << humidity()<< altitude();udpSocket.writeDatagram(datagram, QHostAddress::LocalHost, 5824);
}
main.cpp
#include <QApplication>#include "weatherballoon.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);WeatherBalloon balloon;balloon.show();return app.exec();
}
现在看一下Weather Station客户端的源代码:
class WeatherStation : public QDialog
{Q_OBJECTpublic:WeatherStation(QWidget *parent = 0);private slots:void processPendingDatagrams();private:QUdpSocket udpSocket;QLabel *dateLabel;QLabel *timeLabel;QLabel *temperatureLabel;QLabel *humidityLabel;QLabel *altitudeLabel;QLineEdit *dateLineEdit;QLineEdit *timeLineEdit;QLineEdit *temperatureLineEdit;QLineEdit *humidityLineEdit;QLineEdit *altitudeLineEdit;
};
WeatherStation类派生自QDialog。它监听一个特定的UDP端口,解析任何到来的数据报(来自于Weather Balloon),并且把它们的内容显示到5个只读的QLineEdit中。这里唯一需要注意的私有变量是QUdpSocket类型的udpSocket,我们将利用它来接收数据报。
WeatherStation::WeatherStation(QWidget *parent): QDialog(parent)
{udpSocket.bind(5824);connect(&udpSocket, SIGNAL(readyRead()),this, SLOT(processPendingDatagrams()));...
}
在构造函数中,首先把QUdpSocket绑定到WeatherBalloon所传送的端口。因为我们没有指定主机地址,套接字将在运行Weather Station的机器上接收发往任意IP地址的数据报。然后,将套接字的readyRead()信号与提取和显示数据的processPendingDatagrams()私有槽连接起来。
void WeatherStation::processPendingDatagrams()
{QByteArray datagram;do {datagram.resize(udpSocket.pendingDatagramSize());udpSocket.readDatagram(datagram.data(), datagram.size());} while (udpSocket.hasPendingDatagrams());QDateTime dateTime;double temperature;double humidity;double altitude;QDataStream in(&datagram, QIODevice::ReadOnly);in.setVersion(QDataStream::Qt_4_3);in >> dateTime >> temperature >> humidity >> altitude;dateLineEdit->setText(dateTime.date().toString());timeLineEdit->setText(dateTime.time().toString());temperatureLineEdit->setText(tr("%1 C").arg(temperature));humidityLineEdit->setText(tr("%1%").arg(humidity));altitudeLineEdit->setText(tr("%1 m").arg(altitude));
}
当接收到数据报时,就调用processPendingDatagrams()槽。QUdpSocket 将收到的数据报进行排队并让我们可以一次一个地读取它们。通常情况下,应该只有一个数据报,但是不能排除在发射readyRead()信号前发送端连续发送一些数据报的可能性。如果那样的话,可以忽略除最后一个以外的其他所有数据报,因为之前的数据报包含的只是过期的天气情况。
pendingDatagramSize()函数返回第一个待处理的数据报的大小。从应用程序的角度来看,数据报总是作为一个单一的数据单元来发送和接收的。这意味着只要有任意字节的数据可用,就认为整个数据报都可以被读取。readDatagram()调用把第一个待处理的数据报的内容复制到指定的char*缓冲区中(如果缓冲区空间太小,就直接截断数据),并且前移至下一个待处理的数据报。一旦读取了所有的数据报,就把最后一个数据报(包含最新气象状况测量值的数据报)分解为几个部分,并且用新的数据来组装QLineEdit。
int main(int argc, char *argv[])
{QApplication app(argc, argv);WeatherStation station;station.show();return app.exec();
}
最后,在main()中,我们创建并显示WeatherStation。
至此就完成了UDP发送端和接收端的代码。这个应用程序已经尽可能地简单了,它只是由Weather Balloon发送数据报,由Weather Station接收它们。在绝大多数实际应用中,这两个应用程序都需要通过它们的套接字读取和写入。QUdpSocket::writeDatagram()函数可以传递主机地址和端
口号,所以QUdpSocket可以从用bind()绑定的主机和端口读取数据,并且将其写入到其他的主机和端口。
weatherstation.h
#ifndef WEATHERSTATION_H
#define WEATHERSTATION_H#include <QDialog>
#include <QUdpSocket>class QLabel;
class QLineEdit;class WeatherStation : public QDialog
{Q_OBJECTpublic:WeatherStation(QWidget *parent = 0);private slots:void processPendingDatagrams();private:QUdpSocket udpSocket;QLabel *dateLabel;QLabel *timeLabel;QLabel *temperatureLabel;QLabel *humidityLabel;QLabel *altitudeLabel;QLineEdit *dateLineEdit;QLineEdit *timeLineEdit;QLineEdit *temperatureLineEdit;QLineEdit *humidityLineEdit;QLineEdit *altitudeLineEdit;
};#endif
weatherstation.cpp
#include <QtGui>
#include <QtNetwork>#include "weatherstation.h"WeatherStation::WeatherStation(QWidget *parent): QDialog(parent)
{udpSocket.bind(5824);connect(&udpSocket, SIGNAL(readyRead()),this, SLOT(processPendingDatagrams()));dateLabel = new QLabel(tr("Date:"));timeLabel = new QLabel(tr("Time:"));temperatureLabel = new QLabel(tr("Temperature:"));humidityLabel = new QLabel(tr("Humidity:"));altitudeLabel = new QLabel(tr("Altitude:"));dateLineEdit = new QLineEdit;timeLineEdit = new QLineEdit;temperatureLineEdit = new QLineEdit;humidityLineEdit = new QLineEdit;altitudeLineEdit = new QLineEdit;dateLineEdit->setReadOnly(true);timeLineEdit->setReadOnly(true);temperatureLineEdit->setReadOnly(true);humidityLineEdit->setReadOnly(true);altitudeLineEdit->setReadOnly(true);QGridLayout *mainLayout = new QGridLayout;mainLayout->addWidget(dateLabel, 0, 0);mainLayout->addWidget(dateLineEdit, 0, 1);mainLayout->addWidget(timeLabel, 1, 0);mainLayout->addWidget(timeLineEdit, 1, 1);mainLayout->addWidget(temperatureLabel, 2, 0);mainLayout->addWidget(temperatureLineEdit, 2, 1);mainLayout->addWidget(humidityLabel, 3, 0);mainLayout->addWidget(humidityLineEdit, 3, 1);mainLayout->addWidget(altitudeLabel, 4, 0);mainLayout->addWidget(altitudeLineEdit, 4, 1);setLayout(mainLayout);setWindowTitle(tr("Weather Station"));
}void WeatherStation::processPendingDatagrams()
{QByteArray datagram;do {datagram.resize(udpSocket.pendingDatagramSize());udpSocket.readDatagram(datagram.data(), datagram.size());} while (udpSocket.hasPendingDatagrams());QDateTime dateTime;double temperature;double humidity;double altitude;QDataStream in(&datagram, QIODevice::ReadOnly);in.setVersion(QDataStream::Qt_4_3);in >> dateTime >> temperature >> humidity >> altitude;dateLineEdit->setText(dateTime.date().toString());timeLineEdit->setText(dateTime.time().toString());temperatureLineEdit->setText(tr("%1 C").arg(temperature));humidityLineEdit->setText(tr("%1%").arg(humidity));altitudeLineEdit->setText(tr("%1 m").arg(altitude));
}
main.cpp
#include <QApplication>#include "weatherstation.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);WeatherStation station;station.show();return app.exec();
}
Qt4_发送和接收UDP数据报相关推荐
- Qt 如何发送和接收UDP数据报
在Qt4中,提供了QUdpSocket类,由于udp不像tcp,没有连接的概念,所以就没有QUdpServer,监听也是用同一个类,用法如下 #include <QUdpSocket>in ...
- 如何在Linux命令行下发送和接收UDP数据包
众所周知,在传输层有两个常用的协议 TCP 和 UDP,本文介绍在 Linux 命令行下,如何使用 nc 命令发送或接收 UDP 数据包,这些命令的用法对调试 UDP 通信程序将有所帮助. 1. 问题 ...
- 网络编程【UDP数据报套接字编程】
目录 1.网络编程基础 1.1 为什么需要网络编程? 1.2 什么是网络编程 1.3 网络编程中的基本概念 2.Socket套接字 2.1 分类 3.UDP数据报套接字编程 3.1 DatagramS ...
- 【网络编程】Socket套接字;UDP数据报套接字编程;TCP流套接字编程
文章目录 1. 什么是网络编程 2. 网络编程中的基本概念 3. Socket套接字 4 UDP数据报套接字编程 4.1 客户端服务器交互流程 4.2 UDP版本的回显服务 4.3 英译汉服务 5. ...
- 分析udp数据报_深入的理解UDP编程
什么是UDP? UDP是User Datagram Protocol(用户数据报协议)的缩写,它是一个简单的协议,简单到UDP规范RFC0768只有区区3页. UDP是工作在IP层之上的传输层协议,U ...
- 使用DatagramSocket发送、接收数据(Socket之UDP套接字)
2019独角兽企业重金招聘Python工程师标准>>> 创建一个DatagramSocket实例,并将该对象绑定到指定IP地址.指定端口. 通过上面三个构造器中的任意一个构造器即可创 ...
- 分析udp数据报_Linux内核网络udp数据包发送(二)——UDP协议层分析
1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...
- socket简介和udp网络程序-发送、接收数据
socket简介 不同电脑上的进程之间如何通信 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起! 在1台电脑上可以通过进程号(PID)来唯一标识一个进程,但是在网络中这是行不通的. 其实TCP ...
- 25. Python语言 Web 开发 之 Socket 编程 · 第一章 UDP发送与接收数据
UDP发送与接收数据 本章主题 关键词 前导: 计算机网络的发展及基础网络概念 两台电脑的通信 IP地址介绍及分类 IP地址与IP协议 Windows 和 Linux 查看网卡信息 IP地址分类 以太 ...
最新文章
- 递归函数反向显示单链表
- BOOST_VMD_GET_TYPE宏相关的测试程序
- 弃用官方网站!Python 将所有 Bug 迁移到 GitHub 中
- 可搜索的文件? 是的你可以。 选择AsciiDoc的另一个原因
- 城市路(信息学奥赛一本通-T1381)
- (转)Android IPC机制详解
- php易错,PHP学习1:几种常见数据类型及其易错点
- linux 命令笔记
- 邻居把偶然的救急当成了依赖,怎么办?
- 关于身份证OCR识别,你知道多少?
- 【转载】RPG或SLG游戏在线地图编辑器
- 易语言获取硬盘特征字序列号加密特征字
- SpringBoot2.X 单元测试(Junit4.X) 基本配置
- [libtorrent] tracker 逻辑及源码解析(调试)
- 10.计算机基础之程序设计基础
- POI 导出 Excel:字体颜色、行列自适应、锁住、合并单元格、一文搞定……
- 别跑!JAVA!-----------一篇关于JAVA的博客
- SLAE — SecurityTube Linux组装考试
- 数字化教学资源平台html,数字化教学资源
- 键盘上的按键--键码 对应表
热门文章
- Alibaba之MySQL宝典_Alibaba之MySQL宝典流出!极致经典,堪称行业天花板
- 引物设计软件primer_常用生物学软件的安装与应用(三)—Primer6
- 实现一个闹钟_iPhone 闹钟停止时,如何自动播放你喜欢的音乐
- lua协程 unity_unity协程coroutine浅析
- 开发黑名单功能demo_突然让你开发Electron应用-electron特性练习操场-所见即所得的electron...
- 填坑黑苹果(VMware装MacOS) - 修改 Unlocker 补丁源码版
- ubuntu 14.04下练习lua
- 多个模块使用python logging
- css按钮口诀 - CSS BUG顺口溜
- Python学习笔记三(文件操作、函数)