c/c++11封装UDP,支持ipv4和ipv6,支持接收和发送
更新日志
11/06/2021
- 1.增加IPV6
- 2.ipv6通过windows10初步测试
- 3.ipv6包括: 接收和发送
- 5.增加错误代码接口
- 6.本机IPv6截图

- 7.编译通过截图

- 8.ipv6测试结果

30/05/2021
1.增加IPv6,待测
2.全部改为Unicode编码, 无签名
23-05-2021
1.模块内部增加优化
15/12/2020
- cmake重新配置,改为支持modern cmake
- 创建cmake文件夹,并创建spdlog.cmake文件
- 类的成员函数和成员变量重命名
11/06/2021
- 增加IPV6
- ipv6通过windows10初步测试
3.ipv6包括: 接收和发送
5.增加错误代码接口
30/05/2021
1.增加IPv6,待测
2.全部改为Unicode编码, 无签名
简介
- 1.这是一个使用C++11语法封装的UDP,包括: ipv4 和 ipv6
- 2.ipv4支持: 单播、组播、广播; linux + windows10测试通过,接收和发送均成功
- 3.ipv6通过windows10初步测试。收发均成功; 组播待测
- 5.支持接收和发送
- 6.使用cmake管理的项目
- 7.提供了调用范例
- 8.Linux支持仔细测试,最近比较忙。 后期更新
- 9.欢迎留言指导
接口分类
针对使用场景: 初始化, 发送, 接收, 关闭, 如果不接收, 则只有3个接口。 接口函数返回值后面再更新
使用
接收
接收需要重载 iudp.h中的类irecv_data的on_recv_data_函数。 on_recv_data_原型如下:
/// --------------------------------------------------------------------------------
/// @brief: 接收函数,
/// @param: const unsigned char * pdata_recv - 接收的数据
/// @param: const unsigned int recv_data_len - 接收数据长度
/// @return: void
///
/// --------------------------------------------------------------------------------
virtual void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len) = 0;
接收继承范例
- 你可以在 example/main.cc 中找到下面的代码
- 类my_udp继承了类irecv_data类, 并实现函数on_recv_data_
class my_udp : public irecv_data
{
public:
/// ......
/// ......
/// you must override this function to recv data
void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
{
/// -------------------------------------------------------------------------------
/// 1. recv data
std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
for (unsigned int i = 0; i < recv_data_len; i++)
{
if (i == 10)
std:: cout << "\n";
std::cout << pdata_recv[i] << ", ";
}
std::cout << "\n";
}
/// ....
当接收到数据,底层会调用该函数
接收要注意
- 如果需要接收数据,接口类 iudp 的接口 init_ 的第二个参数需要传递继承自 接口类irecv_data的 on_recv_data_ 接口
- 如果不接收数据,接口类 iudp 的接口 init_ 的第二个参数传递 NULL(或nullptr)即可, 也不需要继承 接口类irecv_data
接口类iudp
- iudp提供了udp的初始化、发送数据和关闭,提供了接口 error_id_() 获取错误代码
- 接口返回值详见代码(代码写的比较详细了)
- 接口尽量设计的简洁
代码
/// ----------------------------------------------------------------------------
/// @brief: UDP接口类
/// ----------------------------------------------------------------------------
class iudp
{
public:
virtual ~iudp(){}
/// ------------------------------------------------------------
/// @brief:初始化
/// @param: const udp_param & param - 初始化参数
/// @param: irecv_data * pfunc_recv - 接收对象
/// @return: int
/// 0 - 成功
/// -1 - 失败,param.socket_version_ 传递错误
/// --------------------------------------------------------------
/// ipv4和ipv6错误, 请调用error_id_()获取错误代码
/// 1 - 失败, 端口为0
/// 2 - 失败, 套接字创建失败
/// 3 - 失败,设置发送超时失败
/// 5 - 失败, 设置接收超时失败
/// 6 - 失败, 设置发送缓冲失败
/// 7 - 失败,设置接收缓冲失败
/// 8 - 失败,设置地址宠用失败
/// 9 - 失败, 绑定套接字失败
/// 10 、11、12 - 失败, 设置套接字 组播属性失败
/// 13 - 失败,设置广播失败
/// 15 - 失败,param._cast_type参数值传递错误
/// ------------------------------------------------------------
virtual int init_(const udp_param& param, irecv_data* pfunc_recv /* = nullptr */) = 0;
/// ------------------------------------------------------------
/// @brief:发送数据
/// @param: const unsigned char * psend - 待发送数据
/// @param: const unsigned int len_send - 待发送数据长度
/// @return: int
/// -1 - 失败。初始化socket版本错误
/// 0 - 成功
/// 1 - 失败, 参数【psend】为空或 【len_max_send】等于0 或则len_max_send大于发送缓冲区长度(10k)
/// 2 - 失败,套接字创建失败
/// 3 - 失败, 发送数据失败, 请调用error_id_()
/// ------------------------------------------------------------
virtual int send_(const unsigned char* psend, const unsigned int send_len) = 0;
/// --------------------------------------------------------------------------------
/// @brief: 关闭
/// @return: int
/// 0 - 成功
/// 其他, 失败
/// --------------------------------------------------------------------------------
virtual int shutdown_() = 0;
/// ------------------------------------------------------------
/// @brief:返回错误ID
/// @return: int
///
/// ------------------------------------------------------------
virtual int error_id_() = 0;
};
创建和销毁
创建
- 调用 iudp.h 中的 udp_create_() 可创建iudp。
- 函数说明
/// --------------------------------------------------------------------------------
/// @brief: 创建 udp对象
/// @return: lib_udp *
/// NULL- 创建失败
/// != null - 成功
/// --------------------------------------------------------------------------------
lib_udp_api iudp * udp_create_();
销毁
- 调用 iudp.h 中的udp_release_(iudp* pudp) 可销毁udp_create_创建的对象
- 函数说明
/// --------------------------------------------------------------------------------
/// @brief: 释放申请的资源, 内部释放后,见其设置为NULL
/// @param: iudp * pudp - 来自【udp_create_】的创建结果
/// @return: lib_udp_api lib_udp *
/// pudp = NULL
/// --------------------------------------------------------------------------------
lib_udp_api iudp * udp_release_(iudp* pudp);
- 调用范例
pudp_ = udp_release_(pudp_);
项目地址
接口使用范例
- 你可以在 example/main.cc中找到下面的代码
代码
接收
/// to recv data, you must inherit udpsocket_recv class
class my_udp : public irecv_data
{
public:
/// constructor
my_udp()
{
if (NULL == pudp_)
pudp_ = udp_create_();//// std::unique_ptr<iudp>(lib_udp::udp_create_()).get();
}
/// deconstructor
virtual ~my_udp()
{
pudp_ = udp_release_(pudp_);
}
/// you must override this function to recv data
void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
{
/// -------------------------------------------------------------------------------
/// 1. recv data
std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
for (unsigned int i = 0; i < recv_data_len; i++)
{
if (i == 10)
std:: cout << "\n";
std::cout << pdata_recv[i] << ", ";
}
std::cout << "\n";
}
/// -------------------------------------------------------------------------------
int init_(udp_param& param)
{
if (pudp_)
return pudp_->init_(param, this);
return -20000;
}
///
int send_(const char *psend, const int len_send)
{
if (pudp_)
return pudp_->send_((const unsigned char*)psend, len_send);
return -20000;
}
///
int shutdown_()
{
if (pudp_)
return pudp_->shutdown_();
return -20000;
}
int error_id_()
{
if (pudp_)
return pudp_->error_id_();
return -20000;
}
private:
iudp* pudp_ = NULL;
};
初始化、发送、关闭
/// -------------------------------------------------------------------------------
/// 1. to prepare params to initialize
udp_param param;
param._is_log_debug = false;
param._cast_type = lib_udp::udp_multi_cast;
param._port_dst = 10086;
param._recv_loop = true;
param.socket_version_ = kipv6;
#ifdef _WIN32
char arr_ipv4[] = "10.0.0.5";
#elif __linux__
char arr_ipv4[] = "192.168.15.129";
#else
char arr_ipv4[] = "10.1.1.3";
#endif///
std::cout << "local IP = " << arr_ipv4 << std::endl;
char arr_dst[] = "233.0.0.11";
//param.dest_ip_.value_ = std::string(arr_dst);
//param.local_ip_.value_ = std::string(arr_ipv4);
std::string str_ipv6;
int indexxxx = 0;
for (auto list_item : ip6_list)
{
str_ipv6 = list_item;
if (3 == indexxxx)
break;
++indexxxx;
}
param.dest_ip_.value_ = std::string("FF02::1");
param.local_ip_.value_ = str_ipv6;/// ip6_list.front();
/// -------------------------------------------------------------------------------
/// 1. to create
std::unique_ptr<my_udp> pmy_udp(new(std::nothrow) my_udp);
//my_udp* pmy_udp = new(std::nothrow) my_udp;
/// failure
if (!pmy_udp)
{
std::cout << "\n my_udp crated failure\n";
#ifdef _WIN32
system("pause");
#endif ///_WIN32
return 0;
}
/// -------------------------------------------------------------------------------
/// 2. to initialize udp
int ret = 0;
ret = pmy_udp->init_(param);
if (0 != ret)
{
std::cout << "\ninit error , id = " << ret << ", error id=" << pmy_udp->error_id_() << "\n\n";
ret = pmy_udp->shutdown_();
if (0 != ret)
std::cout << "\nshutdown error , id = " << ret << "\n";
#ifdef _WIN32
system("pause");
#endif ///_WIN32
return 0;
}
//pmy_udp->shutdown_();
////delete pmy_udp;
////pmy_udp = NULL;
//return 0;
std::cout << "\n init_ip4 success\n";
/// -------------------------------------------------------------------------------
/// 4. to send data
char arr[] = "1234567890";
for (int i = 0; i < 1; i++)
{
int send_len = pmy_udp->send_(arr, strlen(arr));
/// to output the result
std::cout << "udp send, send length = " << send_len << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
}
/// to recv data, it needs to rest
std::cout << "\n---------------------------main 1111----------------------------\n";
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
std::cout << "\n---------------------------main 2222----------------------------\n";
pmy_udp->shutdown_();
std::cout << "\n---------------------------main 3333----------------------------\n";
std::cout << "\nudp has closed\n";
c/c++11封装UDP,支持ipv4和ipv6,支持接收和发送的更多相关文章
- [Linux]Linux下开启snmp支持IPV4和IPV6
SNMP简介 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组资源 ...
- 修改SS配置文件使其同时支持IPV4和IPV6网络
将/etc/shadowsocks-libev/config.json文件中的 "server":"0.0.0.0", 修改为: "server&qu ...
- oracle11G 同时支持IPV4和IPV6配置
1.修改listener.ora文件 LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ...
- 《网络编程》IPv4 与 IPv6 相互操作
前言 因为互联网终端不断添加.IPv4 地址长度(32位)已不可以满足要求.所以出现了 IPv6地址(128位).可是现有应用程序大部分还是採用 IPv4 地址形式,所以必须解决 IPv4 与 IPv ...
- [Linux]Linux下yaf发送IPV4和IPV6的IPfix
一.IPFIX与NetFlow 一.IPFIX 全称IP Flow Information Export,即IP流信息输出,是网络流量监测的国际标准.IPFIX是IETF的一个工作组,它的主要工作就是 ...
- 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等
开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...
- IPv6下网络编程socket, TCP和UDP例子,以及兼容IPV4和IPV6的类
一.TCP socket ipv6与ipv4的区别 服务器端源代码如下: #include <stdio.h> #include <stdlib.h> #include < ...
- NGINX 加载动态模块(NGINX 1.9.11开始增加加载动态模块支持)
NGINX 1.9.11开始增加加载动态模块支持,从此不再需要替换nginx文件即可增加第三方扩展.目前官方只有几个模块支持动态加载,第三方模块需要升级支持才可编译成模块. tinywan@tinyw ...
随机推荐
- 如何构建自己的KEGG数据库
本文转自Y叔公众号 自己KEGG数据库好处: 可重复性好 没网也可以进行分析 步骤 1 在KEGG官网找到自己物种的3字符缩写 2 加载Y叔获取kegg.db 的R包 1 ##安装Y叔的包 2 lib ...
- R语言与医学统计图形-【13】ggplot2几何对象之盒形图
ggplot2绘图系统--几何对象之盒形图 参数: geom_boxplot(mapping = , #lower,middle,upper,x,ymax,ymin必须(有默认) #alpha/col ...
- Linux-centos7设置静态IP地址
参考:https://blog.csdn.net/sjhuangx/article/details/79618865
- 04 Windows安装python运行环境
安装python运行环境 使用微信扫码关注微信公众号,并回复:"Python工具包",免费获取下载链接! 1.卸载程序(电脑未装此程序,跳过此过程) 卸载这两个程序 出现下图所示, ...
- tomcat在eclipse上发布,Perference下的server找不到解决办法
help--->Install New software得到如下所示 下面work with选项的内容与你的eclipse版本有关 我的eclipse版本为eclipse-java-2019-0 ...
- 30个类手写Spring核心原理之环境准备(1)
本文节选自<Spring 5核心原理> 1 IDEA集成Lombok插件 1.1 安装插件 IntelliJ IDEA是一款非常优秀的集成开发工具,功能强大,而且插件众多.Lombok是开 ...
- 【leetcode】598. Range Addition II
You are given an m x n matrix M initialized with all 0's and an array of operations ops, where ops[i ...
- 内存管理——new delete expression
C++申请释放内存的方法与详情表 调用情况 1.new expression new表达式在申请内存过程中都发生了什么? 编译器将new这个分解为下面的主要3步代码,①首先调用operator new ...
- 转 序列化Serializable和Parcelable的区别详解
什么是序列化,为什么要进行序列化 答:对象要进行传输(如:activity 与activity间 ,网络间 进程间等等).存储到本地就必须进行序列化 . 这种可传输的状态就是序列化. 怎么序列化??两 ...
- JavaIO——System对IO的支持、序列化
1.系统类对IO的支持 在我们学习PriteWriter.PrintStream里面的方法print.println的时候是否观察到其与我们之前一直使用的系统输出很相似呢?其实我们使用的系统输出就是采 ...