udp通讯部分封装

 关于udp通讯使用的相关封装,有组播有单播,写的比较乱,后续看看有没有时间完善,写的更清楚详细

#pragma once#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>#include <errno.h>class GOE_Udp
{
public:GOE_Udp(){socket_fd = sock = sendfd = recvfd = 0;}~GOE_Udp(){if (recvfd > 0)close(recvfd);if (sendfd > 0)close(sendfd);if (sock > 0)close(sock);if (socket_fd > 0)close(socket_fd);}const char *GetName() { return "GOE_Udp"; }// 初始化接收参数, 包括端口,超时时间(-1表示阻塞), 多播IP, 绑定设备名(该变量只有多播IP非空的情况才有效)// 如果不接收数据, 可以不调用void InitRecvParams(int recvport, unsigned timeoutInMs = -1, const char *multiRecvIP = NULL, const char *nameDev = "eth0"){if (recvport <= 0)perror("recvport error"); //g_error/*创建 socket*/recvfd = socket(AF_INET, SOCK_DGRAM, 0);if (recvfd < 0)perror("Udp init Recv socket");struct sockaddr_in loc_addr;/*设置 sockaddr_in 结构体中相关参数*/memset(&loc_addr, 0, sizeof(loc_addr));loc_addr.sin_family = AF_INET;loc_addr.sin_addr.s_addr = htonl(INADDR_ANY);loc_addr.sin_port = htons(recvport);printf("recvport = %d, timeoutImMs = %d\n", recvport, timeoutInMs);if (0 == timeoutInMs){printf("set nonblock\n");fcntl(recvfd, F_SETFL, O_NONBLOCK);}else{int timeoutInSec = timeoutInMs / 1000;int timeoutInUs = (timeoutInMs - timeoutInSec * 1000) * 1000;struct timeval timeout = {timeoutInSec, timeoutInUs};setsockopt(recvfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));printf("set timeoutInMs = %d\n", timeoutInMs);}if (multiRecvIP != NULL && multiRecvIP[0] != '\0'){printf("isMultiRecv on , ip = %s\n", multiRecvIP);struct ip_mreq mreq;mreq.imr_multiaddr.s_addr = inet_addr(multiRecvIP);mreq.imr_interface.s_addr = htonl(INADDR_ANY);if (setsockopt(recvfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){perror("setsockopt");}if (nameDev != NULL){struct ifreq ifr;memset(&ifr, 0, sizeof(struct ifreq));strncpy(ifr.ifr_name, nameDev, strlen(nameDev));if (setsockopt(recvfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(struct ifreq)) < 0){
//					perror("bind device %s error: %m", nameDev);perror("setsockopt");}}}int flag = 1;if (setsockopt(recvfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int)) < 0)perror("setsockopt SO_REUSEADDR error");elseprintf("set SO_REUSEADDR successful\n");int opt_val;socklen_t opt_len = sizeof(opt_val);if (getsockopt(recvfd, SOL_SOCKET, SO_RCVBUF, &opt_val, &opt_len) < 0){perror("fail to getsockopt");}printf("before: recv_buf = %dk\n", opt_val / 1024);if (opt_val < 9 * 1024 * 1024){opt_val = 9 * 1024 * 1024;setsockopt(recvfd, SOL_SOCKET, SO_RCVBUF, (char *)&opt_val, opt_len);if (getsockopt(recvfd, SOL_SOCKET, SO_RCVBUF, &opt_val, &opt_len) < 0){perror("fail to getsockopt");}printf("after: recv_buf = %dk\n", opt_val / 1024);}flag = bind(recvfd, (struct sockaddr *)&loc_addr, sizeof(struct sockaddr));if (flag < 0)perror("UdpInit bind");}// 初始化发送参数, 包括目的ip 和目的port, 这两者可以都不指定, 但调用write时,需要注意传递参数// 如果不发送数据, 可以不调用void InitSendParams(const char *dstIp = NULL, int dstPort = 0){/*创建 socket*/sendfd = socket(AF_INET, SOCK_DGRAM, 0);if (sendfd < 0)perror("Udp init Send socket");if (dstIp != NULL && dstPort > 0){memset(&dst_addr, 0, sizeof(dst_addr));dst_addr.sin_family = AF_INET;dst_addr.sin_addr.s_addr = inet_addr(dstIp);dst_addr.sin_port = htons(dstPort);printf("dstip = %s, dstport = %d\n", dstIp, dstPort);}elseprintf("dstip or dstport may be error");int opt_val;socklen_t opt_len = sizeof(opt_val);if (getsockopt(sendfd, SOL_SOCKET, SO_SNDBUF, &opt_val, &opt_len) < 0){perror("fail to getsockopt");}printf("before: send_buf = %dk\n", opt_val / 1024);int sendBufSize = 8 * 1024 * 1024;if (opt_val < sendBufSize) //!< 如果当前发送缓冲区小于给定缓冲区大小,则扩大缓冲区{opt_val = sendBufSize;setsockopt(sendfd, SOL_SOCKET, SO_SNDBUF, (char *)&opt_val, opt_len);if (getsockopt(sendfd, SOL_SOCKET, SO_SNDBUF, &opt_val, &opt_len) < 0){perror("fail to getsockopt");}printf("after: send_buf = %dk\n", opt_val / 1024);}}void InitMultiSendParams(const char *dstIp = NULL, int dstPort = 0 ,const char* LocalIp = NULL,int LocalPort = 0){// 创建 UDP Socket 并加入组播组sock = socket(AF_INET, SOCK_DGRAM, 0);memset(&addr, 0, sizeof(struct sockaddr_in));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(LocalIp); // 本地地址addr.sin_port = htons(LocalPort); // 本地端口if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {perror("bind failed");}struct ip_mreq mreq;mreq.imr_multiaddr.s_addr = inet_addr(dstIp); // 目标组播地址mreq.imr_interface.s_addr = inet_addr(LocalIp); // 本地地址if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) < 0) {perror("setsockopt failed");}}void InitInSendParams(const char* dstIp = NULL,int dstPort = 0){sockfd = socket(AF_INET, SOCK_DGRAM, 0);memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr(dstIp);servaddr.sin_port = htons(dstPort);}int InSend(char* buffer,int buflen){int ret = sendto(sockfd, buffer, buflen, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));return ret;}// 1. 如果客户端想知道发送方 IP 地址,提供存放点分十进制的指针 srcip ,大小至少20// 2. 如果客户端想知道发送方 port, 提供整形指针用于输出// 3. 可以单独获取 ip 和 portint read(char *out, int bufLen, char *srcip = NULL, int *srcport = NULL){if (recvfd == 0){perror("recvport is not appointed\n");return 0;}static socklen_t len = sizeof(struct sockaddr);int ret = -1;ret = recvfrom(recvfd, out, bufLen, 0, (struct sockaddr *)&src_addr, &len);if (ret > 0){if (srcip != NULL){inet_ntop(AF_INET, (void *)&(src_addr.sin_addr), srcip, 16);}if (srcport != NULL)*srcport = ntohs(src_addr.sin_port);}if (ret < 0 && errno == EWOULDBLOCK)ret = 0;return ret;}// 1. 如果 istoSrc 为真, 将把数据返回给来源// 2. 如果 dstip 和 dstport 设置正确,也将发送该地址// 3. 1和2可以同时发送,不会冲突int write(const char *in, int bufLen, bool istoSrc = false, const char *dstip = NULL, int dstport = 0){if (sendfd == 0){perror("dstip or dstport may not be appointed\n");return 0;}int nwrite = -1;if (istoSrc)nwrite = sendto(sendfd, in, bufLen, 0, (struct sockaddr *)&src_addr, sizeof(struct sockaddr));if (dstip != NULL && dstport > 0){struct sockaddr_in dst;memset(&dst, 0, sizeof(struct sockaddr_in));dst.sin_family = AF_INET;dst.sin_addr.s_addr = inet_addr(dstip);dst.sin_port = htons(dstport);nwrite = sendto(sendfd, in, bufLen, 0, (struct sockaddr *)&dst, sizeof(struct sockaddr));}else{nwrite = sendto(sendfd, in, bufLen, 0, (struct sockaddr *)&dst_addr, sizeof(struct sockaddr));}if (nwrite != bufLen){perror("send failed");return 0;}elsereturn nwrite;}int MultiCwrite(const char *psend,int buflen,int eachsend ,const char *destip = NULL, int destport = 0){// 组播发送数据struct sockaddr_in dest_addr;memset(&dest_addr, 0, sizeof(struct sockaddr_in));dest_addr.sin_family = AF_INET;dest_addr.sin_addr.s_addr = inet_addr(destip); // 目标组播地址dest_addr.sin_port = htons(destport); // 目标端口int ret = 0;int nsend = 0;int nremain = buflen;while(nremain >= eachsend){ret += sendto(sock, psend + nsend, eachsend, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));nsend += eachsend;nremain -= eachsend;}if(nremain > 0){ret += sendto(sock, psend + nsend,nremain, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));nsend += nremain;}return ret;}//拆包发送int Cwrite(const char *psend,int buflen,int eachsend){int ret = 0;int nsend = 0;int nremain = buflen;while(nremain >= eachsend){ret += sendto(sendfd, psend + nsend,eachsend, 0 ,(struct sockaddr *)&dst_addr,sizeof(struct sockaddr));nsend += eachsend;nremain -= eachsend;}if(nremain > 0){ret += sendto(sendfd, psend + nsend,nremain, 0, (struct sockaddr *)&dst_addr, sizeof(struct sockaddr));nsend += nremain;}return ret;}private:int recvfd;					 // 用于接收的 socket 描述符int sendfd;					 // 用于发送的 socket 描述符int socket_fd;				 // 用于发送的 socket 描述符int sock;                    //int sockfd;                  //InSendstruct sockaddr_in addr;struct sockaddr_in dst_addr; // 调用write函数时,若没有指定地址,将会发往InitSendParams()传进来的地址struct sockaddr_in src_addr; // 存放发送方地址struct sockaddr_in servaddr; //存放服务器端地址
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/37001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pycharm导入内置库或者第三方库时标红,no module named ‘xxx‘

各版本的Pycharm都有可能会出现这样的问题&#xff1a;有些时候内置库和第三方库被标红为“No module named xxx”&#xff0c;而自己的库却能被正常导入。 本人是在使用远程ssh解释器时遇到的。实际运行该代码文件时&#xff0c;能够正常运行&#xff08;若不能正常运行则可能…

uniApp vue2 vue3配置代理

vue2配置代理 在manifest.json中增加如下配置 "h5" : {"router" : {"mode" : "history"},"devServer" : {"disableHostCheck" : true,"proxy" : {"/api" : {"target" : "请…

基于lio-sam的重定位和增量式建图

文章目录 遇到的问题解决思路预览效果详细过程预先构建地图订阅初始估计姿态加载全局地图ICP配准计算初始位姿参考遇到的问题 为了复用上个生命周期录制的轨迹,我需要用到重定位功能,现有的开源方案中,可以实现该功能,但存在以下问题:在预先构建的地图之外,无法实现定位…

uboot中内存DDR测试之mtest使用

相关代码路径: cmd/mem.c配置: make ARCHarm CROSS_COMPILEaarch64-linux-gnu- menuconfigCC cmd/mem.o cmd/mem.c: In function do_mem_mtest: cmd/mem.c:883:10: error: CONFIG_SYS_MEMTEST_START undeclared (first use in this function); did you mean CONFIG_SYS_…

教你如何找视频、音乐素材

很多时候&#xff0c;视频剪辑从业者都面临着寻找视频素材和音乐素材的问题。没有剪辑影视的视频素材&#xff0c;视频被层层水印覆盖&#xff0c;剪辑出来的视频效果不是很好。今天就给大家分享一些视频、音乐素材网站&#xff0c;再也不用为找素材头疼了&#xff01; 教你如何…

铁塔基站直流侧电能计量模块AMC16-DETT-安科瑞黄安南

AMC16-DETT 基站直流电能计量模块主要是针对有共享需求&#xff0c;且开关电源无分用户电量计量功能的基站而设计的。仪表可对六个回路的直流电能进行计量&#xff0c;并可为配套的霍尔传感器提供工作电流&#xff0c;同时可通过上位机软件实现零漂校准&#xff0c;具有遥测、遥…

网络爬虫的原理

网络爬虫的原理 网络爬虫&#xff0c;作为信息检索和数据分析的重要工具&#xff0c;其原理的核心在于模拟人类浏览网页的行为&#xff0c;通过自动化的方式从互联网上收集所需的数据。在了解了网络爬虫的基本原理后&#xff0c;我们可以进一步探讨其在实际应用中的工作机制以…

自动化邮件通知:批处理脚本的通讯增强

自动化邮件通知&#xff1a;批处理脚本的通讯增强 引言 批处理脚本在自动化任务中扮演着重要角色&#xff0c;无论是在系统管理、数据处理还是日常任务调度中。然而&#xff0c;批处理脚本的自动化能力可以通过集成邮件通知功能得到显著增强。当脚本执行完毕或在执行过程中遇…

一键解决外勤难题,精细化管理轻松get!

行程打卡是企业总部和分店、销售管理与销售、行政与员工保持信息对称的重要方式&#xff0c;也是区域负责人、督导和行政日常重要的工作之一。 行程打卡不仅承载着确保品牌运营的标准性和一致性的目标&#xff0c;同时也是为了收集行程各阶段存在的问题和不足&#xff0c;对后续…

kubernetes之CRI详解

如何更好的用好Kubernetes CRI&#xff1f;本文尝试从CRI原理及作用、CRI执行流程、常见CRI及其优缺点、最佳实践及历史演进等方面进行阐述。希望对您有所帮助&#xff01; 一、Kubernetes CRI 原理及作用 CRI&#xff08;Container Runtime Interface&#xff0c;容器运行时…

MySQL 高性能配置详解与最佳实践

MySQL 高性能配置详解与最佳实践 优化MySQL的配置是提升数据库性能的关键步骤。下面详细介绍了一些常见的MySQL配置参数及其最优设置&#xff0c;适用于中型到大型应用场景。这些配置项应根据实际的硬件资源和工作负载进行调整。 1. InnoDB 相关配置 1.1. innodb_buffer_poo…

什么是div移动指令?如何用vue自定义指令实现?

目录 一、Vue.js框架介绍二、vue自定义指令directive三、什么是div移动指令四、使用vue自定义指令directive写一个div移动指令 一、Vue.js框架介绍 Vue.js是一个用于构建用户界面的渐进式JavaScript框架。它设计得非常灵活&#xff0c;可以轻松地被集成到现有的项目中&#xf…

免费分享:2021年全国30米分辨率最大NDVI数据集(附下载方法)

气候变化及其对陆地生态系统的影响已成为核心议题&#xff0c;备受社会各界的瞩目。植被作为地理环境的关键构成部分&#xff0c;是气候变迁与人文活动对环境影响的敏感晴雨表。其中&#xff0c;归一化植被指数&#xff08;NDVI&#xff09;可以作为衡量地面植被状况的重要指标…

专访ATFX首席战略官Drew Niv:以科技创新引领企业高速发展

在金融科技创新的浪潮中&#xff0c;人才是推动企业高速发展的核心驱动力&#xff0c;优质服务是引领企业急速前行的灯塔。作为差价合约领域的知名品牌&#xff0c;ATFX高度重视人才引进工作&#xff0c;秉持“聚天下英才而用之”的理念&#xff0c;在全球范围内广揽科技精英&a…

反无人机技术详解

无人机反制技术旨在对抗未经授权或有潜在危害的无人机活动。业内已经开发了多种技术来解决无人机在不同环境下带来的日益增长的挑战&#xff0c;包括安全、隐私和安全性。涉及到的关键技术有软杀伤和硬杀伤两种手段。软杀伤如RF干扰、GPS欺骗、通信信号截获、网络攻击、声学对抗…

Nginx反向代理实现Vue跨域注意事项

1、通过搜索引擎访问Nginx官网——免费使用——NGINX开源版(免费下载)或者通过以下链接直接访问Nginx下载页面下载对应的版本(下载页面)。以下以1.24.0为例 2、修改nginx的配置文件&#xff0c;在conf文件夹下&#xff0c;文件名为nginx.conf&#xff1b;以下是我修改完的配置…

Zabbix如何帮助企业将监控数据转化为竞争优势

By Fernanda Moraes 在我们生活的高度互联世界中&#xff0c;变化以越来越快和激烈的速度发生。这影响了消费者的认知与行为&#xff0c;迫使零售商寻找更有效的方式来吸引客户。Linx 是 StoneCo 集团旗下的一家公司&#xff0c;也是零售技术专家&#xff0c;Linx了解这一点&am…

深度挖掘数据资产,洞察业务先机:利用先进的数据分析技术,精准把握市场趋势,洞悉客户需求,为业务决策提供有力支持,实现持续增长与创新

在当今日益激烈的商业竞争环境中&#xff0c;企业想要实现持续增长与创新&#xff0c;必须深入挖掘和有效运用自身的数据资产。数据不仅是企业运营过程中的副产品&#xff0c;更是洞察市场趋势、理解客户需求、优化业务决策的重要资源。本文将探讨如何通过利用先进的数据分析技…

java虚拟机栈帧操作

虚拟机栈(Virtual Machine Stack)是虚拟机(如JVM、Python VM等)用来管理方法调用和执行的栈结构。它主要用于存储方法调用的相关信息,包括局部变量、操作数栈、动态链接和方法返回地址等。 java虚拟机栈操作的基本元素就是栈帧,栈帧主要包含了局部变量表、操作数栈、动态…

Android 复习layer-list使用

<shape android:shape"rectangle"> <size android:width"1dp" android:height"100px" /> <solid android:color"#FFFFFF" /> </shape> 通过shape画线段,通过 <item android:gravity"left|top"…