C++ Enet通信封装

C++ Enet通信封装

    • 接口封装
    • 使用举例

Enet底层封装的是UDP通信,本文介绍了enet如何实现可靠udp传输的代码封装

接口封装

1)User_Enet_Listen监听端口函数

int User_Enet_Listen(const char *ip, int port, ENetHost **host)
{    ENetAddress address;  if(!strcmp(ip, "*"))ip = "0.0.0.0";if(enet_address_set_host_ip(&address, ip)){fprintf(stderr, "enet_address_set_host_ip %s fail", ip);return -1;}address.port = port;assert(host);*host = enet_host_create(&address, 1, 1, 0, 0);if(NULL==*host){fprintf(stderr, "enet_host_create %s:%d fail", address.host, address.port);return -1;}int size = 1024*1024*1024;if(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, size)){fprintf(stderr, "enet set server socket rcvbuf %d bytes fail", size);}return 0;
}

2)User_Enet_Accept接受链接函数

int User_Enet_Accept(ENetHost *host, unsigned int timeout, ENetPeer **peer)
{int ret;ENetEvent event;ret = enet_host_service(host, &event, timeout);if(ret > 0){        if(event.type != ENET_EVENT_TYPE_CONNECT){if(event.type == ENET_EVENT_TYPE_RECEIVE)enet_packet_destroy(event.packet);fprintf(stderr, "enet_host_service event type %d is not connect", event.type);return -1;}         assert(peer);*peer = event.peer;         }else if(0==ret){fprintf(stderr, "enet_host_service timeout %d", timeout);return -1;         }else{fprintf(stderr, "enet_host_service fail");return -1;}return 0;
}

3)User_Enet_Connect建立连接函数

int User_Enet_Connect(const char *srv_ip, int srv_port, unsigned int conn_timeout, unsigned int rw_timeout, ENetHost **host, ENetPeer **peer)
{    assert(host);*host = enet_host_create(NULL, 1, 1, 0, 0);if(NULL==*host){fprintf(stderr, "enet_host_create fail");goto fail;}if(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, 1024*1024*1024)){fprintf(stderr, "enet set server socket rcvbuf 1M bytes fail");}ENetAddress srv_addr;if(enet_address_set_host_ip(&srv_addr, srv_ip)){fprintf(stderr, "enet_address_set_host_ip %s fail", srv_ip);goto fail;}srv_addr.port = srv_port;assert(peer);*peer = enet_host_connect(*host, &srv_addr, 1, 0); if(*peer==NULL){fprintf(stderr, "enet_host_connect %s:%d fail", srv_ip, srv_port);goto fail;}enet_peer_timeout(*peer, 0, rw_timeout, rw_timeout);int cnt = 0;ENetEvent event;while(1){ret = enet_host_service(*host, &event, 1);if(ret == 0){    if(++cnt >= conn_timeout){ fprintf(stderr, "enet_host_service timeout %d", conn_timeout);goto fail;}}else if(ret > 0){if(event.type != ENET_EVENT_TYPE_CONNECT){     fprintf(stderr, "enet_host_service event type %d is not connect", event.type);goto fail;}break; //connect successfully}else{fprintf(stderr, "enet_host_service fail");        goto fail;}}#ifdef _DEBUGchar local_ip[16], foreign_ip[16];ENetAddress local_addr;enet_socket_get_address((*host)->socket, &local_addr);enet_address_get_host_ip(&local_addr, local_ip, sizeof(local_ip));enet_address_get_host_ip(&(*peer)->address, foreign_ip, sizeof(foreign_ip));printf("%s:%d connected to %s:%d", local_ip, loca_addr.port, foreign_ip, (*peer)->address.port);#endif return 0;     fail:if(*host) enet_host_destroy(*host); return -1;}

4)User_Enet_DisConnect断开连接函数

 int User_Enet_DisConnect(ENetHost *host, ENetPeer *peer)
{int ret;#ifdef _DEBUGchar local_ip[16], foreign_ip[16];ENetAddress local_addr;enet_socket_get_address(host->socket, &local_addr);enet_address_get_host_ip(&local_addr, local_ip, sizeof(local_ip));enet_address_get_host_ip(&peer->address, foreign_ip, sizeof(foreign_ip));printf("%s:%d is disconnected from %s:%d", local_ip, local_addr.port, foreign_ip, peer->address.port);#endifENetEvent event;enet_peer_disconnect(peer, 0);while((ret = enet_host_service(host, &event, peer->roundTripTime)) > 0){switch (event.type){case ENET_EVENT_TYPE_RECEIVE:enet_packet_destroy (event.packet);break;case ENET_EVENT_TYPE_DISCONNECT:ret = 0;goto disconn_ok;}}ret = 0==ret ? 1 : -1;fprintf(stderr, "enet_host_service with timeout %d %s", peer->roundTripTime, 1==ret?"timeout":"failure");enet_peer_reset(conn->peer);disconn_ok:    enet_host_destroy(host);return ret;}

5)User_Enet_SendMsg发送数据函数

int User_Enet_SendMsg(ENetHost *host, ENetPeer *peer, ENetPacket *packet){int ret;if(enet_peer_send(peer, 0, packet)){fprintf(stderr, "enet send packet %lu bytes to peer fail", packet->dataLength);return -1;}ret = enet_host_service(host, NULL, peer->roundTripTime);if(ret >= 0){if(peer->state == ENET_PEER_STATE_ZOMBIE){fprintf(stderr, "enet peer state is zombie");return -1;}return packet->dataLength;}else{fprintf(stderr, "enet host service %u millsecond failure", peer->roundTripTime);return -1;}}int User_Enet_Send(ENetHost *host, ENetPeer *peer, const void *buf, size_t len){int ret;ENetPacket *packet = enet_packet_create(buf, len, ENET_PACKET_FLAG_RELIABLE);if(NULL==packet){        fprintf(stderr, "enet create packet %lu bytes fail", sizeof(int)+len);return -1;}return User_Enet_SendMsg(host, peer, packet);}

6)User_Enet_RecvMsg接收数据函数

int User_Enet_RecvMsg(ENetHost *host, ENetPeer *peer, ENetPacket **packet, unsigned int timeout){int ret;ENetEvent event;ret = enet_host_service(host, &event, timeout);if(ret > 0){if(event.peer != peer){fprintf(stderr, "enet receive peer is not matched");goto fail;}if(event.type != ENET_EVENT_TYPE_RECEIVE){fprintf(stderr, "enet receive event type %d is not ENET_EVENT_TYPE_RECEIVE", event.type);goto fail;}*packet = event.packet;return*packet)->dataLength;fail:enet_packet_destroy(event.packet);return -1;}else {fprintf(stderr, "enet receive %u millsecond %s", timeout, ret?"failure":"timeout");return -1;        }}int User_Enet_Recv(ENetHost *host, ENetPeer *peer, void *buf, size_t maxlen, unsigned int timeout) {ENetPacket *packet;if(-1==User_Enet_RecvMsg(host, peer, &packet, timeout))return -1;if(packet->dataLength > maxlen) {fprintf(stderr, "enet packet data length %d is greater than maxlen %lu", packet->dataLength, maxlen);return -1;}memcpy(buf, packet->data, packet->dataLength);enet_packet_destroy(packet);return packet->dataLength;}

7)User_Enet__WaitAck 等待所有确认函数
发送数据的确认,需根据对端状态判断是否断线

 int User_Enet__WaitAck (ENetHost *host, ENetPeer *peer, unsigned int timeout){int ret, cnt = 0;while((ret = enet_host_service(host, NULL, 1)) >= 0){        if(enet_peer_is_empty_sent_reliable_commands(peer, 0, ENET_PROTOCOL_COMMAND_SEND_RELIABLE|ENET_PROTOCOL_COMMAND_SEND_FRAGMENT))return 0;if(peer->state == ENET_PEER_STATE_ZOMBIE){fprintf(stderr, "enet peer state is zombie");return -1;}if(0==ret && ++cnt>=timeout){return 1;}}fprintf(stderr, "enet host service fail");return -1;}

使用举例

客户端:
User_Enet_Connect->User_Enet_SendMsg或User_Enet_Send->User_Enet_WaitAck
服务端:
User_Enet_Listen->User_Enet_Accept->User_Enet_Recv或是User_Enet_RecvMsg

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

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

相关文章

无涯教程-JavaScript - ISODD函数

描述 如果数字为奇数,则ISODD函数返回TRUE,如果数字为偶数,则返回FALSE。 语法 ISODD (number) 争论 Argument描述Required/OptionalNumber 要测试的值或表达式。 如果number不是整数,则将其截断。 Required Notes 您可以在执行计算之前使用此功能测试单元格的内容。 如果…

BUG:阿里巴巴图标库引入链接后,icon有时候会不显示的话svg下载到本地使用

忽然icon图标就不显示,但是代码、icon链接地址都没有发生变化 解决办法:将icon图标下载到本地,记住前后引用本地的名字要保持一致

软件设计师学习笔记9-进程调度

目录 1. PV操作 1.1进程的同步与互斥 1.1.1互斥 1.1.2同步 1.2 PV操作 1.2.1信号量 1.2.2 PV操作的概念 2.信号量与PV操作 2.1 PV操作与互斥模型 2.2 PV操作与同步模型 2.3 互斥与同步模型结合 3.前趋图与PV操作 1. PV操作 1.1进程的同步与互斥 1.1.1互斥 互斥&…

DOM文档对象模型

10.DOM文档对象模型 1.DOM节点的组成 元素节点 属性节点 文本节点 标签就是元素节点 class id的值 等 就是属性节点 文字,空格,换行就是文本节点 <div class"box">你好</div><元素节点 属性节点>文本不节点</元素节点>2如何获取页面元素…

Apache HTTPD 漏洞复现

文章目录 Apache HTTPD 漏洞复现1. Apache HTTPD 多后缀解析漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.4 获取GetShell1.5 漏洞防御 2. Apache HTTPD 换行解析漏洞-CVE-2017-157152.1 漏洞描述2.2 漏洞复现2.3 漏洞利用2.4 修复建议 3. Apache HTTP Server_2.4.49 路径遍历和…

无涯教程-JavaScript - ISREF函数

描述 如果指定的值是参考,则ISREF函数返回逻辑值TRUE。否则返回FALSE。 语法 ISREF (value) 争论 Argument描述Required/OptionalvalueA reference to a cell.Required Notes 您可以在执行任何操作之前使用此功能测试单元格的内容。 适用性 Excel 2007,Excel 2010,Exce…

LCP 50. 宝石补给

每位勇者初始都拥有一些能量宝石&#xff0c; gem[i] 表示第 i 位勇者的宝石数量。现在这些勇者们进行了一系列的赠送&#xff0c;operations[j] [x, y] 表示在第 j 次的赠送中 第 x 位勇者将自己一半的宝石&#xff08;需向下取整&#xff09;赠送给第 y 位勇者。 在完成所有…

【LeetCode】210. 课程表 II——拓扑排序

题目链接&#xff1a;210. 课程表 II 题目描述&#xff1a; 现在你总共有 numCourses 门课需要选&#xff0c;记为 0 到 numCourses - 1。给你一个数组 prerequisites &#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示在选修课程 ai 前 必须 先选修 bi 。 例如…

【计算机网络】网络编程接口 Socket API 解读(7)

Socket 是网络协议栈暴露给编程人员的 API&#xff0c;相比复杂的计算机网络协议&#xff0c;API 对关键操作和配置数据进行了抽象&#xff0c;简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍&#xff0c;从而更好的理解 socket 编程。…

【Flowable】使用UEL整合Springboot从0到1(四)

前言 在前面我们介绍了Springboot简单使用了foleable以及flowableUI的安装和使用&#xff0c;在之前我们分配任务的处理人的时候都是通过Assignee去指定固定的人的。这在实际业务中是不合适的&#xff0c;我们希望在流程中动态的去解析每个节点的处理人&#xff0c;当前flowab…

9.12 C++作业

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…

【Android知识笔记】UI体系(三)

View动画原理 当我们创建View动画时,一般使用类似如下代码: ScaleAnimation scaleAnimation = new ScaleAnimation(0,1,0,1); scaleAnimation.setDuration(3000); scaleAnimation.setFillAfter

Jest单元测试相关

官方文档&#xff1a;jest 中文文档 1、模拟某个函数&#xff0c;并返回指定的结果 使用Jest测试JavaScript(Mock篇) 有这样一个需求&#xff0c;mock掉Math.random方法&#xff08;0&#xff08;包括&#xff09;&#xff5e;1之间&#xff09;&#xff0c;使其返回指定的0…

华为Java工程师面试题

常见问题&#xff1a; 什么是Java虚拟机&#xff08;JVM&#xff09;&#xff1f;它与现实中的计算机有什么不同&#xff1f;Java中的基本数据类型有哪些&#xff1f;它们的范围是什么&#xff1f;什么是引用类型&#xff1f;Java中的引用类型有哪些&#xff1f;什么是对象&am…

PostgreSQL的主从复制方式

主从复制方式 PostgreSQL支持多种主从复制&#xff08;Master-Slave Replication&#xff09;方式&#xff0c;用于创建可靠的数据备份和故障容错解决方案。以下是几种常见的主从复制方式&#xff1a; 同步复制&#xff08;Synchronous Replication&#xff09;&#xff1a;在…

计算机网络TCP篇之流量控制

计算机网络TCP篇之流量控制 今天谈一谈我对于tcp流量控制的看法 在网络拓扑中如果发送方节点的发送速率大于接受方节点的接受速率&#xff0c;数据会不断在接受方的缓冲区累积&#xff0c;直到接受方的缓冲区满的时候&#xff0c;发送方继续发送数据&#xff0c;这时候接受方无…

Redis群集

目录 1、redis群集三种模式 2、Redis 主从复制 2.1 主从复制的作用 2.2 主从复制流程 2.3 搭建Redis 主从复制 3、Redis 哨兵模式 3.1 哨兵模式的作用 3.2 故障转移机制 3.3 主节点的选举 4、Redis 群集模式 4.1 集群的作用 4.2 Redis集群的数据分片 4.3 搭建Redis…

算法通关村18关 | 回溯模板如何解决分割回文串问题

1. 分割回文串 题目 LeetCode131 分割回文串&#xff0c;给你一个字符串s&#xff0c;请你将s分割成一些字串&#xff0c;使每个字串都是回文串&#xff0c;返回s所有可能的分割方案。 回文串是正着和反着读都是一样的字符串。 思路 知道回溯的模板&#xff0c;用回溯的角度思…

用python实现音乐下载

前言 本文背景 最近对音乐比较有需求&#xff0c;想着用自己学的python来实现一下下载需求&#xff0c; 真的是拿着锤子在满世界找钉子&#xff0c;**文末附全部代码**声明&#xff1a; 本文仅作技术交流&#xff0c;禁止用于其他非法途径本文2023年9月15日是可用的&#xff…

漫谈:C语言 值传递 函数参数 指针

C语言麻拐得很。 什么是变量&#xff1f;变量就是内存里面的一个东西&#xff0c;有值。 什么是“值传递”&#xff1f;C语言函数参数调用都是值传递&#xff0c;就是把变量的值给函数。 这里面一个大坑&#xff0c;就是函数参数究竟是什么&#xff1f;很多初学者对“值传递”、…