目录
UDP(User Datagram Protocol 即用户数据报协议)是一个轻量级的,不可靠的,面向数据
报的无连接协议。由于 UDP 的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
UDP 通信示意图如下:

UDP 消息传送有三种模式,分别是单播、广播和组播三种模式。
①单播(unicast): 单播用于两个主机之间的端对端通信,需要知道对方的 IP 地址与端口
②广播(broadcast): 广播 UDP 与单播 UDP 的区别就是 IP 地址不同,广播一般使用广播地址
255.255.255.255,将消息发送到在同一广播(也就是局域网内同一网段) 网络上的每个主机
注意:本地广播信息是不会被路由器转发,所以如果一个服务端在win,另外一个客户端在虚拟机说,这时就需要配置虚拟机的端口转发,这样虚拟机才会连得上服务器。

③组播(multicast): 组播(多点广播),也称为多播,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。
在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播的这种功能,可以一次将数据发送到多个主机,又能保证不影响其他不需要(未加入组)的主机的其他通信。
注意: 单播一样和多播是允许在广域网即 Internet 上进行传输的,而广播仅仅在同一局域网上才能进行。
QT 的 socket 类之间的关系:

QUdpSocket 类提供了一个 UDP 套接字。 QUdpSocket 是 QAbstractSocket 的子类,允许发
送和接收 UDP 数据报。
常用API函数
①构造函数
QUdpSocket::QUdpSocket(QObject *parent = Q_NULLPTR)
②如果至少有一个数据报在等待被读取,则返回true,否则返回false。
bool QUdpSocket::hasPendingDatagrams() const
③服务器绑定端口
bool bind(const QHostAddress &address, quint16 port = 0, BindMode mode = DefaultForPlatform);
④返回第一个待处理的UDP数据报的大小Byte。如果没有可用的数据报,该函数返回-1。
qint64 QUdpSocket::pendingDatagramSize() const
⑤接收数据
qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)
接收一个不大于maxSize字节的数据报并将其存储在data中。发送者的主机地址和端口存储在*address和*port中(除非指针为0)。成功时返回数据报的大小;否则返回-1。
如果maxSize太小,数据报的其余部分将被丢失。为了避免数据丢失,在试图读取数据报之前,应调用pendingDatagramSize()来确定未决数据报的大小。如果maxSize为0,数据报将被丢弃。
⑥发送数据
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
将数据报以大小的方式发送到端口端口的主机地址。成功时返回发送的字节数,否则返回-1。
数据报总是被写成一个块。数据报的最大尺寸与平台高度相关,但可以低至8192字节。如果数据报太大,这个函数将返回-1,error()将返回DatagramTooLargeError。
一般来说,发送大于512字节的数据报是不利的,因为即使它们被成功发送,在到达最终目的地之前,它们很可能被IP层分割开来。
1.创建QUdpSocket对象
mSocket = new QUdpSocket(this);
②绑定地址和端口号
msocket->bind(ip,端口号);
③收到数据时,会触发readyRead()信号,自定义readPendingDatagrams()进行读取数据;
connect(msocket,&QUdpSocket::readyRead, this,&Widget::readPendingDatagrams);
④在while循环中读取数据,只要有数据,就一直读取并处理。
void Server::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) //数据报等待被读取{
//数据缓冲区QByteArray arr;
//调整缓冲区的大小和收到的数据大小一致
arr.resize(mSocket->bytesAvailable()); //接收数据
mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);
//将arr.data转为字符串即可
QString str = arr.data();
}
}
通信(先接收) 收到数据会触发信号readyRead, 通过QUdpSocket对象的readDatagram函数来接收数据 。
readyRead()信号在数据报到达时发出。在这种情况下, hasPendingDatagrams()返回 true。调用 pendingDatagramSize()来获取第一个待处理数据报的大小,并调用 readDatagram()接收数据。
注意:当接收到readyRead()信号时,一个传入的数据报应该被读取,否则这个信号将不会被发送到下一个数据报。
⑤发送数据
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
若是广播消息,与单播消息不同的是将目标 IP 地址换成了广播地址,一般广播地址为 255.255.255.255,也可以使用QHostAddress::Broadcast获取广播地址。
QHostAddress peerAddr = QHostAddress::Broadcast;
只需要将客户端发送数据:writeDatagram的IP地址改为广播地址即可。
①创建QUdpSocket对象
mSocket = new QUdpSocket(this);
②发送数据到指定的地址和端口号
writeDatagram(数据,接收方ip,接收方端口号);
发送的数据要是QByteArray类型,Qt中将字符串转为QByteArray可以使用.toUtf8函数。
头文件
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QWidget>
#include <QtNetwork>
QT_BEGIN_NAMESPACE
namespace Ui { class UdpServer; }
QT_END_NAMESPACE
class UdpServer : public QWidget
{
Q_OBJECT
public:
UdpServer(QWidget *parent = nullptr);
~UdpServer();
private slots:
void on_pushButton_start_clicked();
void on_pushButton_send_clicked();
void readPendingDatagrams();
private:
Ui::UdpServer *ui;
//Udp服务器
QUdpSocket *mSocket;
//通信的ip和端口,用于获取发送者的 IP 和端口
QHostAddress addr;
quint16 port;
};
#endif // UDPSERVER_H
源文件
#include "udpserver.h"
#include "ui_udpserver.h"
UdpServer::UdpServer(QWidget *parent)
: QWidget(parent)
, ui(new Ui::UdpServer)
{
ui->setupUi(this);
}
UdpServer::~UdpServer()
{
delete ui;
}
//启动
void UdpServer::on_pushButton_start_clicked()
{
//1.创建QUdpSocket对象
mSocket = new QUdpSocket(this);
//2.连接接收数据信号和槽
QObject::connect(mSocket,&QUdpSocket::readyRead,this,&UdpServer::readPendingDatagrams);
//3.绑定
mSocket->bind(QHostAddress::Any,ui->spinBox->value());
//连接回车发送的信号和槽
QObject::connect(ui->lineEdit,&QLineEdit::returnPressed,this,&UdpServer::on_pushButton_send_clicked);
//禁止端口号和启动按钮
ui->spinBox->setEnabled(false);
ui->pushButton_start->setEnabled(false);
}
void UdpServer::on_pushButton_send_clicked()
{
//获取发送的数据
QByteArray arr = ui->lineEdit->text().toUtf8();
//发送
mSocket->writeDatagram(arr,addr,port);
//显示发送的内容
ui->textBrowser->insertPlainText("send:"+QString(arr)+"\n");
//情况lineEdit
ui->lineEdit->clear();
}
void UdpServer::readPendingDatagrams()
{
//数据缓冲区
QByteArray arr;
while(mSocket->hasPendingDatagrams())
{
//调整缓冲区的大小和收到的数据大小一致
arr.resize(mSocket->bytesAvailable());
//接收数据
mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);
//显示
ui->textBrowser->insertPlainText(addr.toString()+":"+QString(arr)+"\n");
//使能发送按钮和编辑框
ui->lineEdit->setEnabled(true);
ui->pushButton_send->setEnabled(true);
}
}
头文件
#ifndef UDPCILENT_H
#define UDPCILENT_H
#include <QWidget>
#include <QtNetwork>
QT_BEGIN_NAMESPACE
namespace Ui { class UdpCilent; }
QT_END_NAMESPACE
class UdpCilent : public QWidget
{
Q_OBJECT
public:
UdpCilent(QWidget *parent = nullptr);
~UdpCilent();
private slots:
void on_pushButton_send_clicked();
void readPendingDatagrams();
private:
Ui::UdpCilent *ui;
//UDP客户端
QUdpSocket *mSocket;
};
#endif // UDPCILENT_H
源文件
#include "udpcilent.h"
#include "ui_udpcilent.h"
UdpCilent::UdpCilent(QWidget *parent)
: QWidget(parent)
, ui(new Ui::UdpCilent)
{
ui->setupUi(this);
//1.创建QUdpSocket
mSocket = new QUdpSocket(this);
//2.通信(接收)
QObject::connect(mSocket,&QUdpSocket::readyRead,this,&UdpCilent::readPendingDatagrams);
//连接回车发送的信号和槽
QObject::connect(ui->lineEdit_send,&QLineEdit::returnPressed,this,&UdpCilent::on_pushButton_send_clicked);
}
UdpCilent::~UdpCilent()
{
delete ui;
}
//发送
void UdpCilent::on_pushButton_send_clicked()
{
//获取发送的数据
QByteArray arr = ui->lineEdit_send->text().toUtf8();
//发送
//mSocket->writeDatagram(arr,QHostAddress(ui->lineEdit_ip->text()),ui->spinBox->value());
mSocket->writeDatagram(arr,QHostAddress::Broadcast,ui->spinBox->value());
//显示发送的内容
ui->textBrowser->insertPlainText("send:"+QString(arr)+"\n");
//情况lineEdit
ui->lineEdit_send->clear();
}
void UdpCilent::readPendingDatagrams()
{
QHostAddress addr; //用于获取发送者的 IP 和端口
quint16 port;
//数据缓冲区
QByteArray arr;
while(mSocket->hasPendingDatagrams())
{
//调整缓冲区的大小和收到的数据大小一致
arr.resize(mSocket->bytesAvailable());
//接收数据
mSocket->readDatagram(arr.data(),arr.size(),&addr,&port);
//显示
ui->textBrowser->insertPlainText(addr.toString()+":"+QString(arr)+"\n");
}
}
结果:

我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'
在Rails中,什么是集成更新模型某些元素的UDP监听过程的最佳方式(特别是它将向其中一个表添加行)。简单的答案似乎是在同一个进程中使用UDP套接字对象启动一个线程,但我什至不清楚我应该在哪里做适合Rails方式的事情。有没有一种巧妙的方法来开始收听UDP?具体来说,我希望能够编写一个UDPController并在每个数据报消息上调用一个特定的方法。理想情况下,我希望避免在UDP上使用HTTP(因为它会浪费一些在这种情况下非常宝贵的空间),但我完全控制消息格式,因此我可以为Rails提供它需要的任何信息。 最佳答案 Rails是一个
功能需求:主机使用一个串口,与两个从机进行双向通信,主机向从机发送数据,从机能够返回数据,由于结构限制,主机与从机之间只有3根线(电源、地、数据线),并且从机上没有设物理的电源开关,需要通过与主机连接的数据线来控制开机,总结如下:1、数据线只有1根2、能够双向通信3、主机能够控制从机开机4、主机可以单独向1个从机发数据,也可以同时向两个从机发送数据根据需求,设计出如下电路:工作原理分析:VCC_24V_IN、GND、LINE_L(LINE_R)三根线接线连接到从机,电源开启电路是从机内部的电源控制。开机的逻辑:*主机先上电,LINE_L因为主机的R1上拉而有高电平,使Q6导通,Q5的G极电压被
我有一个RaspberryPiTFT7"触摸屏显示器,我想创建一个简单的应用程序来显示和输出系统数据(即CPU使用率、温度等)。我注意到目前常见的实现方法是使用pygame库输出到显示器连接到的帧缓冲区/dev/fb1。我想执行相同的操作,但使用Ruby,因为我更熟悉这门语言。有人可以为我指明正确的方向,让我知道如何开始吗?我查看了rubygame和gosu库,它们似乎能够做我想做的事情,即绘制屏幕,但我找不到任何关于如何将输出定向到的信息帧缓冲区本身。 最佳答案 rubycorelib有一个IO您应该能够使用该类将输出定向
目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式 2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置 3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一
假设我有一个包含帖子的博客应用程序。创建帖子后,将创建一个工作人员来处理一些后台操作。我的情况是,在提交表单后我想显示某种加载消息(gif加载器等),当工作人员完成时我想隐藏加载消息并显示工作人员提供的一些数据。我的问题是,传达工作人员已完成工作并将其显示在用户前端的最佳方式是什么。worker回调看起来像这样defworker_finish#messagetheuserend 最佳答案 我认为您可能忽略了拥有后台工作人员的意义,基本上,您试图做的是弄巧成拙。--如果用户提交表单并且你在你的Controller中排队作业,只是为了让
我正在尝试访问我无法控制的SOAP服务。其中一个操作称为ProcessMessage。我按照这个例子生成了一个SOAP请求,但我收到一条错误消息,指出该操作不存在。我将问题追溯到生成信封正文的方式。USER658e702d5feff1777a6c741847239eb5d6d86e482010-02-18T02:05:25Zpassword......ProcessMessage标签应该是:这就是示例Java应用程序生成它时的样子,并且可以正常工作。该标记是我的Ruby应用程序生成的内容与示例Java应用程序之间的唯一区别。有什么方法可以去掉那个标签前面的"wsdl:"命名空间并添加这