更新日志

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

  1. cmake重新配置,改为支持modern cmake
  2. 创建cmake文件夹,并创建spdlog.cmake文件
  3. 类的成员函数和成员变量重命名

11/06/2021

  1. 增加IPV6
  2. 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_原型如下:

  1. /// --------------------------------------------------------------------------------
  2. /// @brief: 接收函数,
  3. /// @param: const unsigned char * pdata_recv - 接收的数据
  4. /// @param: const unsigned int recv_data_len - 接收数据长度
  5. /// @return: void
  6. ///
  7. /// --------------------------------------------------------------------------------
  8. 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_
  1. class my_udp : public irecv_data
  2. {
  3. public:
  4. /// ......
  5. /// ......
  6. /// you must override this function to recv data
  7. void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
  8. {
  9. /// -------------------------------------------------------------------------------
  10. /// 1. recv data
  11. std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
  12. for (unsigned int i = 0; i < recv_data_len; i++)
  13. {
  14. if (i == 10)
  15. std:: cout << "\n";
  16. std::cout << pdata_recv[i] << ", ";
  17. }
  18. std::cout << "\n";
  19. }
  20. /// ....

当接收到数据,底层会调用该函数

接收要注意

  • 如果需要接收数据,接口类 iudp 的接口 init_ 的第二个参数需要传递继承自 接口类irecv_dataon_recv_data_ 接口
  • 如果不接收数据,接口类 iudp 的接口 init_ 的第二个参数传递 NULL(或nullptr)即可, 也不需要继承 接口类irecv_data

接口类iudp

  • iudp提供了udp的初始化、发送数据和关闭,提供了接口 error_id_() 获取错误代码
  • 接口返回值详见代码(代码写的比较详细了)
  • 接口尽量设计的简洁

代码

  1. /// ----------------------------------------------------------------------------
  2. /// @brief: UDP接口类
  3. /// ----------------------------------------------------------------------------
  4. class iudp
  5. {
  6. public:
  7. virtual ~iudp(){}
  8. /// ------------------------------------------------------------
  9. /// @brief:初始化
  10. /// @param: const udp_param & param - 初始化参数
  11. /// @param: irecv_data * pfunc_recv - 接收对象
  12. /// @return: int
  13. /// 0 - 成功
  14. /// -1 - 失败,param.socket_version_ 传递错误
  15. /// --------------------------------------------------------------
  16. /// ipv4和ipv6错误, 请调用error_id_()获取错误代码
  17. /// 1 - 失败, 端口为0
  18. /// 2 - 失败, 套接字创建失败
  19. /// 3 - 失败,设置发送超时失败
  20. /// 5 - 失败, 设置接收超时失败
  21. /// 6 - 失败, 设置发送缓冲失败
  22. /// 7 - 失败,设置接收缓冲失败
  23. /// 8 - 失败,设置地址宠用失败
  24. /// 9 - 失败, 绑定套接字失败
  25. /// 10 、11、12 - 失败, 设置套接字 组播属性失败
  26. /// 13 - 失败,设置广播失败
  27. /// 15 - 失败,param._cast_type参数值传递错误
  28. /// ------------------------------------------------------------
  29. virtual int init_(const udp_param& param, irecv_data* pfunc_recv /* = nullptr */) = 0;
  30. /// ------------------------------------------------------------
  31. /// @brief:发送数据
  32. /// @param: const unsigned char * psend - 待发送数据
  33. /// @param: const unsigned int len_send - 待发送数据长度
  34. /// @return: int
  35. /// -1 - 失败。初始化socket版本错误
  36. /// 0 - 成功
  37. /// 1 - 失败, 参数【psend】为空或 【len_max_send】等于0 或则len_max_send大于发送缓冲区长度(10k)
  38. /// 2 - 失败,套接字创建失败
  39. /// 3 - 失败, 发送数据失败, 请调用error_id_()
  40. /// ------------------------------------------------------------
  41. virtual int send_(const unsigned char* psend, const unsigned int send_len) = 0;
  42. /// --------------------------------------------------------------------------------
  43. /// @brief: 关闭
  44. /// @return: int
  45. /// 0 - 成功
  46. /// 其他, 失败
  47. /// --------------------------------------------------------------------------------
  48. virtual int shutdown_() = 0;
  49. /// ------------------------------------------------------------
  50. /// @brief:返回错误ID
  51. /// @return: int
  52. ///
  53. /// ------------------------------------------------------------
  54. virtual int error_id_() = 0;
  55. };

创建和销毁

创建

  • 调用 iudp.h 中的 udp_create_() 可创建iudp。
  • 函数说明
  1. /// --------------------------------------------------------------------------------
  2. /// @brief: 创建 udp对象
  3. /// @return: lib_udp *
  4. /// NULL- 创建失败
  5. /// != null - 成功
  6. /// --------------------------------------------------------------------------------
  7. lib_udp_api iudp * udp_create_();

销毁

  • 调用 iudp.h 中的udp_release_(iudp* pudp) 可销毁udp_create_创建的对象
  • 函数说明
  1. /// --------------------------------------------------------------------------------
  2. /// @brief: 释放申请的资源, 内部释放后,见其设置为NULL
  3. /// @param: iudp * pudp - 来自【udp_create_】的创建结果
  4. /// @return: lib_udp_api lib_udp *
  5. /// pudp = NULL
  6. /// --------------------------------------------------------------------------------
  7. lib_udp_api iudp * udp_release_(iudp* pudp);
  • 调用范例
  1. pudp_ = udp_release_(pudp_);

项目地址

giteegithub

接口使用范例

  • 你可以在 example/main.cc中找到下面的代码

代码

接收

  1. /// to recv data, you must inherit udpsocket_recv class
  2. class my_udp : public irecv_data
  3. {
  4. public:
  5. /// constructor
  6. my_udp()
  7. {
  8. if (NULL == pudp_)
  9. pudp_ = udp_create_();//// std::unique_ptr<iudp>(lib_udp::udp_create_()).get();
  10. }
  11. /// deconstructor
  12. virtual ~my_udp()
  13. {
  14. pudp_ = udp_release_(pudp_);
  15. }
  16. /// you must override this function to recv data
  17. void on_recv_data_(const unsigned char *pdata_recv, const unsigned int recv_data_len)
  18. {
  19. /// -------------------------------------------------------------------------------
  20. /// 1. recv data
  21. std::cout << "\n --------------AAAAAA data length = " << recv_data_len << "\n";
  22. for (unsigned int i = 0; i < recv_data_len; i++)
  23. {
  24. if (i == 10)
  25. std:: cout << "\n";
  26. std::cout << pdata_recv[i] << ", ";
  27. }
  28. std::cout << "\n";
  29. }
  30. /// -------------------------------------------------------------------------------
  31. int init_(udp_param& param)
  32. {
  33. if (pudp_)
  34. return pudp_->init_(param, this);
  35. return -20000;
  36. }
  37. ///
  38. int send_(const char *psend, const int len_send)
  39. {
  40. if (pudp_)
  41. return pudp_->send_((const unsigned char*)psend, len_send);
  42. return -20000;
  43. }
  44. ///
  45. int shutdown_()
  46. {
  47. if (pudp_)
  48. return pudp_->shutdown_();
  49. return -20000;
  50. }
  51. int error_id_()
  52. {
  53. if (pudp_)
  54. return pudp_->error_id_();
  55. return -20000;
  56. }
  57. private:
  58. iudp* pudp_ = NULL;
  59. };

初始化、发送、关闭

  1. /// -------------------------------------------------------------------------------
  2. /// 1. to prepare params to initialize
  3. udp_param param;
  4. param._is_log_debug = false;
  5. param._cast_type = lib_udp::udp_multi_cast;
  6. param._port_dst = 10086;
  7. param._recv_loop = true;
  8. param.socket_version_ = kipv6;
  9. #ifdef _WIN32
  10. char arr_ipv4[] = "10.0.0.5";
  11. #elif __linux__
  12. char arr_ipv4[] = "192.168.15.129";
  13. #else
  14. char arr_ipv4[] = "10.1.1.3";
  15. #endif///
  16. std::cout << "local IP = " << arr_ipv4 << std::endl;
  17. char arr_dst[] = "233.0.0.11";
  18. //param.dest_ip_.value_ = std::string(arr_dst);
  19. //param.local_ip_.value_ = std::string(arr_ipv4);
  20. std::string str_ipv6;
  21. int indexxxx = 0;
  22. for (auto list_item : ip6_list)
  23. {
  24. str_ipv6 = list_item;
  25. if (3 == indexxxx)
  26. break;
  27. ++indexxxx;
  28. }
  29. param.dest_ip_.value_ = std::string("FF02::1");
  30. param.local_ip_.value_ = str_ipv6;/// ip6_list.front();
  31. /// -------------------------------------------------------------------------------
  32. /// 1. to create
  33. std::unique_ptr<my_udp> pmy_udp(new(std::nothrow) my_udp);
  34. //my_udp* pmy_udp = new(std::nothrow) my_udp;
  35. /// failure
  36. if (!pmy_udp)
  37. {
  38. std::cout << "\n my_udp crated failure\n";
  39. #ifdef _WIN32
  40. system("pause");
  41. #endif ///_WIN32
  42. return 0;
  43. }
  44. /// -------------------------------------------------------------------------------
  45. /// 2. to initialize udp
  46. int ret = 0;
  47. ret = pmy_udp->init_(param);
  48. if (0 != ret)
  49. {
  50. std::cout << "\ninit error , id = " << ret << ", error id=" << pmy_udp->error_id_() << "\n\n";
  51. ret = pmy_udp->shutdown_();
  52. if (0 != ret)
  53. std::cout << "\nshutdown error , id = " << ret << "\n";
  54. #ifdef _WIN32
  55. system("pause");
  56. #endif ///_WIN32
  57. return 0;
  58. }
  59. //pmy_udp->shutdown_();
  60. ////delete pmy_udp;
  61. ////pmy_udp = NULL;
  62. //return 0;
  63. std::cout << "\n init_ip4 success\n";
  64. /// -------------------------------------------------------------------------------
  65. /// 4. to send data
  66. char arr[] = "1234567890";
  67. for (int i = 0; i < 1; i++)
  68. {
  69. int send_len = pmy_udp->send_(arr, strlen(arr));
  70. /// to output the result
  71. std::cout << "udp send, send length = " << send_len << "\n";
  72. std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
  73. }
  74. /// to recv data, it needs to rest
  75. std::cout << "\n---------------------------main 1111----------------------------\n";
  76. std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1));
  77. std::cout << "\n---------------------------main 2222----------------------------\n";
  78. pmy_udp->shutdown_();
  79. std::cout << "\n---------------------------main 3333----------------------------\n";
  80. std::cout << "\nudp has closed\n";

c/c++11封装UDP,支持ipv4和ipv6,支持接收和发送的更多相关文章

  1. [Linux]Linux下开启snmp支持IPV4和IPV6

    SNMP简介 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组资源 ...

  2. 修改SS配置文件使其同时支持IPV4和IPV6网络

    将/etc/shadowsocks-libev/config.json文件中的 "server":"0.0.0.0", 修改为: "server&qu ...

  3. oracle11G 同时支持IPV4和IPV6配置

    1.修改listener.ora文件 LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ...

  4. 《网络编程》IPv4 与 IPv6 相互操作

    前言 因为互联网终端不断添加.IPv4 地址长度(32位)已不可以满足要求.所以出现了 IPv6地址(128位).可是现有应用程序大部分还是採用 IPv4 地址形式,所以必须解决 IPv4 与 IPv ...

  5. [Linux]Linux下yaf发送IPV4和IPV6的IPfix

    一.IPFIX与NetFlow 一.IPFIX 全称IP Flow Information Export,即IP流信息输出,是网络流量监测的国际标准.IPFIX是IETF的一个工作组,它的主要工作就是 ...

  6. 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  7. 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等

    开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...

  8. IPv6下网络编程socket, TCP和UDP例子,以及兼容IPV4和IPV6的类

    一.TCP socket ipv6与ipv4的区别 服务器端源代码如下: #include <stdio.h> #include <stdlib.h> #include < ...

  9. NGINX 加载动态模块(NGINX 1.9.11开始增加加载动态模块支持)

    NGINX 1.9.11开始增加加载动态模块支持,从此不再需要替换nginx文件即可增加第三方扩展.目前官方只有几个模块支持动态加载,第三方模块需要升级支持才可编译成模块. tinywan@tinyw ...

随机推荐

  1. Docker Error response from daemon,Docker 换镜像

    Docker换镜像,Docker  pull.Docker search 失败出现以下错误 Error response from daemon: Get https://index.docker.i ...

  2. k8s集群中部署Rook-Ceph高可用集群

    先决条件 为确保您有一个准备就绪的 Kubernetes 集群Rook,您可以按照这些说明进行操作. 为了配置 Ceph 存储集群,至少需要以下本地存储选项之一: 原始设备(无分区或格式化文件系统) ...

  3. C#生成编号

    //自动生成账单编号 public string GetNewPoID(string Prefix) { string NewPoID = Prefix + DateTime.Now.Year.ToS ...

  4. 学习java的第十四天

    一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...

  5. day08 文件属性

    day08 系统目录 今日内容 一.重要目录 1./usr 2./var 3./proc 二.文件的属性 1.文件属性的介绍 2.文件属性的详述 3.企业案例 /usr 安装第三方软件的目录: 1./ ...

  6. Spark相关知识点(一)

    spark工作机制,哪些角色,作用. spark yarn模式下的cluster模式和client模式有什么区别.

  7. 零基础学习java------day14-----泛型,foreach,可变参数,数组和集合间的转换,Set,Map,

    1.泛型(jdk1.5以后出现) https://www.cnblogs.com/lwbqqyumidi/p/3837629.html#!comments (1)为什么要用泛型? 限制集合,让它只能存 ...

  8. HongYun项目启动

    一个前后端分离项目的启动顺序: 数据库启动, stams 后台springboot启动 中间路由启动,比如nginx,如果有的话:有这一层,后台可以设置负载均衡,可以动态部署 前端启动

  9. mysql锁相关讲解及其应用

    一.mysql的锁类型 了解Mysql的表级锁 了解Mysql的行级锁 (1) 共享/排它锁(Shared and Exclusive Locks) 共享锁和排他锁是InnoDB引擎实现的标准行级别锁 ...

  10. CountDownLatch原理

    正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.在Java并发中,countdownlatch的概念是一 ...