Qt中通过C++ 实现udp广播报文

2023-05-16

Qt UDP消息交互

  • udp广播原理介绍
  • 客户端实现方法
    • 客户端思路
    • 实现代码
  • 服务端实现方法
    • 服务端思路
    • 实现代码

udp广播原理介绍

UDP是面向非连接的网络交互协议,在UDP交互中,存在客户端和服务端,客户端(Client)主要来发送报文,服务端(Server)接收来自客户端的报文,在进行报文交互的时候,UDP是非连接的,客户端发送一个报文到指定端口,然后服务端监听了这个端口,如果收到这个报文,然后就进行处理,如果收不到,或者因为处理报文的消息队列太大,被抛弃了,就导致服务端无法收到这个报文。给大家举个例子,敌人扔了一个手雷过来,队长喊了一声“卧倒!”,有的士兵耳朵正好听到,就立马卧倒了,有的士兵可能正在带着耳机听音乐,没听到这个“报文”,结果就。。。了,所以,UDP的广播是一种不可靠的可以一对多的网络交互。
请添加图片描述

客户端实现方法

客户端思路

1、主要利用C++的 socket 创建一个udp socket.
2、利用setsockopt() 对socket进行设置参数选项
3、创建一个struct sockaddr_in 类型的对象,并进行初始化协议类型(ipv4或ipv6)、接收地址(广播地址)和接收端口号。
4、利用 sendto() 函数将udp报文进行发送。

实现代码

client头文件

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <string>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

using namespace std;
class UdpClient
{
public:
    UdpClient();
    void Init(const int port);
    void StartBroadCast(const string info);
    static void* UdpBroadCast(void * arg);

private:
    struct sockaddr_in m_clientAddr;
    string             m_sendMsg;
    pthread_t          m_tids;
};

#endif // UDPCLIENT_H

client cpp文件

#include "udpclient.h"
#include <QDebug>
#include <qjsondocument.h>
#include <QJsonParseError>
#include <QFile>
#include <QJsonObject>
#include <QJsonArray>
#include <QStringLiteral>

UdpClient::UdpClient()
{
    bzero(&m_clientAddr, sizeof(m_clientAddr));
    m_tids = 0;
}

void UdpClient::Init(const int port)
{
    m_clientAddr.sin_family = AF_INET;
    m_clientAddr.sin_addr.s_addr = INADDR_BROADCAST; //广播 IP
    m_clientAddr.sin_port = htons(port); //指定接收端口
}

void UdpClient::StartBroadCast(string info)
{
    m_sendMsg = info;
    if (m_tids == 0) {
        pthread_create(&m_tids, NULL, UdpBroadCast, (void *)this); // 启动线程来发送报文,将类指针传递到线程内
    }
}

void* UdpClient::UdpBroadCast(void * arg)
{
    int           udpSocket = socket(AF_INET, SOCK_DGRAM, 0);// 创建socket对象
    UdpClient     *udp = (UdpClient *)arg;                   //  接收线程传递的类对象指针
    unsigned long addr = INADDR_BROADCAST;                   //  广播地址

    while (1) {
    	// 设置socket的参数
        int ret = setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &addr, sizeof(addr));
        if (ret != 0) {
            qDebug()<<"[Client] set udp client options failed";
            close(udpSocket);
            return NULL;
        }

        string sendMsg =udp->m_sendMsg;
        size_t sendLen = sendto(udpSocket, udp->m_sendMsg.c_str(), udp->m_sendMsg.length(),
                     0, (struct sockaddr*)&udp->m_clientAddr, sizeof(udp->m_clientAddr));

		// 发送成功后,会返回发送报文的长度,如果返回长度和报文长度一致,则认为发送成功
        if (sendLen != udp->m_sendMsg.length()) {
            qDebug()<<QString("[CLIENT]send msg lenth error: src len: %1 send len: %2")
                      .arg(sendMsg.length()).arg((int)sendLen);
        } else {
            qDebug()<<"[CLIENT]send success:"<<QString::fromStdString(sendMsg);
        }

        sleep(5);  // 等待5s后发送
    }

    close(udpSocket);
    return NULL;
}

服务端实现方法

服务端思路

1、创建struct sockaddr_in 变量,设置协议族,接收地址,接收端口。
2、创建socket 变量,设置协议族
3、bind() 函数绑定socket
4、recvfrom() 来获取当前的udp报文

实现代码

server 头文件

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
#include <functional>
using namespace std;

typedef std::function<void(string)> Fun;
typedef void(*CallFun)(string);

class UdpServer
{
public:
    UdpServer();
    int  Init(const int port, const Fun callbackFun = NULL);  //callbackFun 为收到报文的处理函数
    void setCallBack(Fun func);                               //设置回调函数
    int  startListen();                                       //开始监听接口
    static void* recv(void *args);                            // 接收消息函数

private:
    struct sockaddr_in m_srvAddr;
    int     m_udpSocket;
    Fun     m_msgProcFun;
};

#endif // UDPSERVER_H

server cpp文件

#include "udpserver.h"
#include <string.h>
#include <qdebug.h>
UdpServer::UdpServer()
{
    bzero(&m_srvAddr, sizeof(m_srvAddr));
    m_msgProcFun = NULL;
}

int UdpServer::Init(const int port, const Fun callbackFun)
{
    m_srvAddr.sin_family = AF_INET;
    m_srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    m_srvAddr.sin_port = htons(port);
    m_msgProcFun = callbackFun;
    return startListen();
}

int UdpServer::startListen()
{
    m_udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

    int ret = bind(m_udpSocket,(sockaddr*)&m_srvAddr,sizeof(sockaddr));
    if (ret != 0) {
        return ret;
    }

    pthread_t tids;
    ret = pthread_create(&tids, NULL, recv, (void *)this);        // 采用线程来处理udp报文
    if (ret != 0) {
        qDebug()<<"[SERVER]create thread failed";
        return ret;
    }

    return 0;
}

void* UdpServer::recv(void *args)
{
	sockaddr_in srv_Addr;
    UdpServer*  udp = (UdpServer*)args;
    socklen_t   addr_len = sizeof(srv_Addr);
    char        *buff = new char[100];
    
    while(1) {
        memset(buff, 0, 100);
        size_t sz = recvfrom(udp->m_udpSocket, buff, 100, 0,(struct sockaddr*)&srv_Addr,&addr_len);
        qDebug()<<buff;

        string data = buff;
        data = data.substr(16);  // 取前16个字节的数据
        if (udp->m_msgProcFun) {
            udp->m_msgProcFun(data);
        }
    }

    return NULL;
}

void UdpServer::setCallBack(Fun func)
{
    m_msgProcFun = func;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt中通过C++ 实现udp广播报文 的相关文章

  • 串口接收 DMA FIFO 双缓冲区配置 + 单色OLED屏幕灰度图像显示的抖动算法

    适用于单色OLED屏幕图像显示的抖动算法 Visual studio c 43 43 STM32F4070 96寸单色IIC通信OLED5级灰度串口DMA 双缓冲github 抖动算法原理 DITHER抖动算法是指灰度可以用一定比例的黑白点
  • HTTP请求报文与响应报文

    一 HTTP的请求报文格式 xff1a HTTP的请求报文内容包括 xff1a 请求行 request line 请求头部 header 空行 和 请求数据 request data 四个部分组成 请求行主要包括 xff1a 请求方法 UR
  • c++中char转换为string类型

    写程序遇到一个Bug如下 xff1a char x 61 39 a 39 string str x 这里报错了 当时就有点蒙了 xff0c 查了下string的构造函数 xff1a string string const string am
  • C语言——内存管理问题

    常见的内存错误及解决方法 一 结构体成员指针未初始化 eg span class token macro property span class token directive hash span span class token dire
  • 大端存储和小端存储

    一 大端存储 高字节数据存储在低地址 二 小端存储 低字节数据存储在低地址 注意 xff1a 无论是大端存储还是小端存储 xff0c 读取到的数据为0x0102030405 三 大端存储或小端存储都是由系统设定的 xff0c 其二者区别在于
  • 多播的概念

    一 多播概述 多播 xff1a 数据的收发仅仅在同一组中进行 xff08 相当于我往一个群里发 xff0c 只有加入这个群的人才能收到 xff09 多播的特点 xff1a 多播地址标示一组接口 多播可以用于广域网使用 在IPv4 xff0c
  • 利用C语言编写一个网络分析器

    一 链路层数据格式 mac报文 xff1a 14个字节 二 IP数据报文格式 三 TCP数据报文格式 四 UDP数据报文格式 五 demo xff08 网络分析器 xff09 recvfrom接收链路层帧数据 xff0c 不经过网络层 传输
  • ARP攻击代码(ARP欺骗)

    一 ARP攻击 ARP欺骗攻击原理 xff1a ARP欺骗攻击建立在局域网主机间相互信任的基础上的 比如 xff1a 假设A B C在同一个局域网中 xff0c 网关为192 168 43 1 xff0c IP地址和MAC地址分别假设如下
  • 使用wireshark抓包并分析TCP三次握手

    一 实验过程 1 TCP包抓取及分析过程 确认使用的协议 xff0c 使用HTTP服务 选择https www baidu com 作为目标地址 启动Wireshark软件 xff0c 点击开始抓包后 在浏览器地址输入https www b
  • 使用wireshark抓包并分析TCP四次挥手

    一 四次挥手 第一次挥手 xff1a xff08 FIN 43 ACK xff09 客户端发送FIN 43 ACK包给服务端 xff0c 用来关闭客户端到服务器的数据传送 此时客户端进入FIN WAIT 1状态 第二次挥手 xff1a AC
  • TR-069协议介绍

    一 概念 关于TR 069 协议命名 TR 069 全称 Technical Report 069 是由DSL Forum xff08 一个非盈利性的全球行业联盟 致力于发展宽带网络范 xff09 其成员包括通讯 设备 计算机 网络和服务提
  • FFMPEG关键结构体——AVCodecContext

    一 AVCodecContext结构体 这是一个描述编码器上下文的数据结构 xff0c 包含了众多编码器需要的参数信息 该结构体在libavcodec avcode h中定义 二 常见变量
  • FFMPEG关键结构体——AVIOContext

    一 AVIOContext结构体 这个结构体 xff0c 是FFmpeg中有关io操作的顶层结构体 xff0c 是avio的核心 FFmpeg支持打开本地文件路径和流媒体协议的URL 该结构体在libavformat avio h中定义 二
  • 指针数组和数组指针

    一 什么是指针数组 一个数组 xff0c 若其元素均为指针类型数据 xff0c 称为指针数组 xff0c 也就是说 xff0c 指针数组中的每一个元素都存放一个地址 xff0c 相当于一个指针变量 span class token keyw
  • Symfony学习笔记之翻译组件-----translation总结

    过际化 xff08 internationalization xff0c 常被简写为i18n xff09 xff0c 是指将字符串和其他一些具有区域特征的片段 xff0c 从你的程序中提取 xff08 abstract xff09 出来 x
  • 为什么要配环境变量?path用来干什么?

    提出问题 xff1a 为什么要配环境变量 xff1f 配环境变量解决了什么 xff1f xff08 阿菜进来看哈嘛 xff09 注 xff1a 环境变量具体概念自行百度百科 概念理解 xff1a 环境变量相关概念 path路径 xff1a
  • Ubuntu18.04无wifi图标安装Realtek RTL8111/8168/8411网卡驱动详解

    这是本人第一次写博客 xff0c Ubuntu系统网卡驱动问题也已经遇到过两次了 xff0c 本次写下博客作为记录 xff0c 希望对遇到同样问题的同学有所帮助 电脑 xff1a 联想E14 系统 xff1a Ubuntu18 04 使用网
  • ROS echo 命令出现报错Cannot load message class for .... Are your messages built?解决办法

    1 把别人录制的bag包拿到自己的系统环境中echo某个topic想查看内容 xff0c 键入echo命令后弹出Are your messages built 错误 xff0c 原因 xff1a 没有在自己的工作空间下的devel incl
  • Pixhawk---基于NSH的Firmware开发与调试

    xfeff xfeff 版权声明 xff1a 本文为博主 原创 文章 xff0c 未经博主允许可以转载 xff0c 注明博客出处 xff1a http blog csdn net FreeApe 目录 43 相关知识了解 1 Nuttx系统
  • Ubuntu18.04安装Terminator后切换回默认终端

    step1 打开一个终端 xff0c 键入以下命令 xff1a sudo update alternatives config x terminal emulator step2 输入你的密码 xff0c 会看到可选项 xff0c 选择 u

随机推荐