mynet开源库
1.介绍
个人实现的c++开源网络库.
2.软件架构
1.结构图

2.基于event的自动分发机制

3.多优先级分发队列,延迟分发队列

内部event服务于通知机制的优先级为0,外部event优先级为1.
当集中处理分发的event_callback时,若激活了更高优先级的event_callback,可在当前event_callback回调处理结束.进入下次时间循环,以便高优先级event_callback及时得到处理.
4.主动分发event_callback来向工作线程提交回调任务

5.通信对象的高效缓存区管理
5.1.以携带管理信息的可变尺寸块作为基础缓存单位

5.2.以可变尺寸块的链式队列构成的缓存区

5.3.块的可复用
对由于消耗而需释放的块,采用缓存而非释放来管理.

释放块时候,依据块容量,释放到缓存指定容量下块的容器.
需要新块时,依据所需容量,先从缓存取块,取不到时,再动态分配新的块.
5.4.连接对象的连接管理
采用一个互斥锁,实现连接对象上连接建立过程,连接断开过程至多只有一个并发.
a. 连接过程

b.断开过程

c.断开投递快速响应
设置手动分发event_callback的优先级为0,借助event_callback的多优先级分发队列.可使得当前event_callback回调处理结束,即可开始下轮循环,从而快速处理分发的高优先级的event_callback.
5.5.连接对象高效锁管理
a. 通过连接锁实现连接建立,连接断开的串行化.
b. 可读事件处理,收包回调无锁处理.
因为可读事件及收包回调只在单个工作线程引发,且通过连接建立,连接断开的串行化处理.收包过程及其回调可以实现为无锁的.
c. 通过发送锁实现发送缓存区并发管理
用户线程执行发送,工作线程可写事件执行异步发送分别充当了发送缓存的生产者,消费者.我们用发送互斥锁进行并发管理.
5.6.高效的io复用
a. 采用epoll作为io复用器,其比select,poll在管理大规模事件监控时性能更优异.
b. 只在必要时注册连接对象可写event到event_base.
b.1. 连接建立过程,我们将其注册到event_base,以便实现连接结果异步处理.
b.2. 用户线程向发送缓存写入新数据时,我们将其注册到event_base以便实现数据在可写事件中的异步发送.
b.3. 在异步发送里,判断发送缓存为空时,自动移除可写event.以便减少不必要的事件分发.
5.7.简单易用
a. 以c++实现.
b. 以工厂模式管理资源.
c. 接口定义清晰,详见使用说明.
系统要求
1.支持c++11
2.支持cmake
3.linux系统
安装教程
1.在mynet/build下执行:cmake ../
2.在mynet/build下执行:make
3.在mynet/build/demo下执行:./srv_test开启服务端
4.在mynet/build/demo下执行:./cli_test开启客户端
使用说明
1.客户端demo
#include "ifactory.h"
#include "ilog.h"
#include "iclient.h"
#include "define.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thread>
#include <chrono>
#include <mutex>
#include <iostream>
#include <fstream>
#include <endian.h>std::mutex mtx;
std::ofstream logFile("cli_logfile.txt", std::ios_base::out);
void logcb(mynet::LOGLEVEL nLevel, const char *msg){//if(nLevel == mynet::LOGLEVEL::EVENT_LOG_ERR){pthread_t thread_id = pthread_self(); std::lock_guard<std::mutex> lock(mtx); logFile << "tid:" << (uint32_t)thread_id << " level: " << (int32_t)nLevel << ": msg: " << msg << std::endl; //}
}struct Msg1{int32_t nLen;int32_t nType;int32_t nMsg1;char strName[100];Msg1(){nLen = CalculateSize();nType = 1;}static int32_t CalculateSize(){return 112;}void Serialize(char* lpOut){int32_t nTmpLen = htobe32(nLen);memcpy(lpOut, (char*)&nTmpLen, 4);int32_t nTmpType = htobe32(nType);memcpy(lpOut+4, (char*)&nTmpType, 4);int32_t nMsg = htobe32(nMsg1);memcpy(lpOut+8, (char*)&nMsg, 4);memcpy(lpOut+12, strName, 100);}Msg1* DeSerialize(char* lpIn){Msg1* lpM = new Msg1();int32_t nTmpLen = *(int32_t*)lpIn;lpM->nLen = be32toh(nTmpLen);int32_t nTmpType = *(int32_t*)((char*)lpIn+4);lpM->nType = be32toh(nTmpType);int32_t nMsg = *(int32_t*)(lpIn+8);lpM->nMsg1 = be32toh(nMsg);memcpy(lpM->strName, lpIn+12, 100);return lpM;}
};
struct Msg2{int32_t nLen;int32_t nType;int32_t nMsg2;char strName1[100];char strName2[100];Msg2(){nLen = CalculateSize();nType = 2;}static int32_t CalculateSize(){return 212;}void Serialize(char* lpOut){int32_t nTmpLen = htobe32(nLen);memcpy(lpOut, (char*)&nTmpLen, 4);int32_t nTmpType = htobe32(nType);memcpy(lpOut+4, (char*)&nTmpType, 4);int32_t nMsg = htobe32(nMsg2);memcpy(lpOut+8, (char*)&nMsg, 4);memcpy(lpOut+12, strName1, 100);memcpy(lpOut+112, strName2, 100);}Msg2* DeSerialize(char* lpIn){Msg2* lpM = new Msg2();int32_t nTmpLen = *(int32_t*)lpIn;lpM->nLen = be32toh(nTmpLen);int32_t nTmpType = *(int32_t*)(lpIn+4);lpM->nType = be32toh(nTmpType);int32_t nMsg = *(int32_t*)(lpIn+8);lpM->nMsg2 = be32toh(nMsg);memcpy(lpM->strName1, lpIn+12, 100);memcpy(lpM->strName2, lpIn+112, 100);return lpM;}
};
class ClientCallback:public mynet::IClientCallback{
public:virtual ~ClientCallback(){printf("~ClientCallback\n");}virtual void OnEvent(short events){printf("recv event %d\n", events);}virtual void OnMessage(char* lpMsg, int32_t nLen){printf("msg len:%d\n", nLen);}
};
int main(){mynet::SetLogCb(logcb);mynet::FactoryConfig stConfig;stConfig.nWorkThreadNum = 1;mynet::IFactory* lpFac = mynet::CreateFactory(stConfig);lpFac->Start();mynet::ClientConfig stCliConfig;stCliConfig.nConnTimeout = 4;stCliConfig.nPort = 13142;strcpy(stCliConfig.strIp, "127.0.0.1");stCliConfig.nThreadIndex = 0;ClientCallback stCall;mynet::IClient* lpCli = lpFac->CreateClient(stCliConfig, &stCall);int32_t nRet = lpCli->DoConnect(13142, stCliConfig.strIp, 4, true, true);printf("conn ret %d\n", nRet);if(nRet != RET_CODE_CONN_SUCC){return 0;}char* lpBuf = (char*)malloc(Msg1::CalculateSize());for(int32_t i = 0; i < 10; i++){Msg1 stM1;stM1.nMsg1 = 11;strcpy(stM1.strName, "StrName1"); stM1.Serialize(lpBuf);int32_t nSend = lpCli->SendData(lpBuf, Msg1::CalculateSize());printf("%d send ret %d\n", i, nSend);}std::this_thread::sleep_for(std::chrono::seconds(6)); lpCli->DoDisconnect(true, true);lpFac->Stop();mynet::DestroyFactory(lpFac);return 0;
}
2.服务端demo
#include "ifactory.h"
#include "ilog.h"
#include "iserver.h"
#include "define.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thread>
#include <chrono>
#include <mutex>
#include <iostream>
#include <fstream>
std::mutex mtx;
std::ofstream logFile("svr_logfile.txt", std::ios_base::out);
void logcb(mynet::LOGLEVEL nLevel, const char *msg){//if(nLevel == mynet::LOGLEVEL::EVENT_LOG_ERR){pthread_t thread_id = pthread_self(); std::lock_guard<std::mutex> lock(mtx); logFile << "tid:" << (uint32_t)thread_id << " level: " << (int32_t)nLevel << ": msg: " << msg << std::endl; //}
}struct Msg1{int32_t nLen;int32_t nType;int32_t nMsg1;char strName[100];Msg1(){nLen = CalculateSize();nType = 1;}static int32_t CalculateSize(){return 112;}void Serialize(char* lpOut){int32_t nTmpLen = htobe32(nLen);memcpy(lpOut, (char*)&nTmpLen, 4);int32_t nTmpType = htobe32(nType);memcpy(lpOut+4, (char*)&nTmpType, 4);int32_t nMsg = htobe32(nMsg1);memcpy(lpOut+8, (char*)&nMsg, 4);memcpy(lpOut+12, strName, 100);}Msg1* DeSerialize(char* lpIn){Msg1* lpM = new Msg1();int32_t nTmpLen = *(int32_t*)lpIn;lpM->nLen = be32toh(nTmpLen);int32_t nTmpType = *(int32_t*)((char*)lpIn+4);lpM->nType = be32toh(nTmpType);int32_t nMsg = *(int32_t*)(lpIn+8);lpM->nMsg1 = be32toh(nMsg);memcpy(lpM->strName, lpIn+12, 100);return lpM;}
};
struct Msg2{int32_t nLen;int32_t nType;int32_t nMsg2;char strName1[100];char strName2[100];static int32_t CalculateSize(){return 212;}void Serialize(char* lpOut){int32_t nTmpLen = htobe32(nLen);memcpy(lpOut, (char*)&nTmpLen, 4);int32_t nTmpType = htobe32(nType);memcpy(lpOut+4, (char*)&nTmpType, 4);int32_t nMsg = htobe32(nMsg2);memcpy(lpOut+8, (char*)&nMsg, 4);memcpy(lpOut+12, strName1, 100);memcpy(lpOut+112, strName2, 100);}Msg2* DeSerialize(char* lpIn){Msg2* lpM = new Msg2();int32_t nTmpLen = *(int32_t*)lpIn;lpM->nLen = be32toh(nTmpLen);int32_t nTmpType = *(int32_t*)(lpIn+4);lpM->nType = be32toh(nTmpType);int32_t nMsg = *(int32_t*)(lpIn+8);lpM->nMsg2 = be32toh(nMsg);memcpy(lpM->strName1, lpIn+12, 100);memcpy(lpM->strName2, lpIn+112, 100);return lpM;}
};class ServerCallback:public mynet::IServerCallback{
public:ServerCallback(){}virtual ~ServerCallback(){printf("~ServerCallback\n");}virtual void OnEvent(int32_t nIndex, short events){printf("index_%d,events_%d\n", nIndex, events);}virtual void OnMessage(int32_t nIndex, char* lpMsg, int32_t nLen){printf("index_%d,len_%d\n", nIndex, nLen);m_lpSvr->SendData(nIndex, lpMsg, nLen);}
public:mynet::IServer* m_lpSvr = nullptr;
};int main(){mynet::SetLogCb(logcb);mynet::FactoryConfig stConfig;stConfig.nWorkThreadNum = 1;mynet::IFactory* lpFac = mynet::CreateFactory(stConfig);lpFac->Start();mynet::ServerConfig stSvrConfig;stSvrConfig.nPort = 13142;stSvrConfig.nListenThreadIndex = 0;ServerCallback stSvrCallback;mynet::IServer* lpSvr = lpFac->CreateServer(stSvrConfig, &stSvrCallback);stSvrCallback.m_lpSvr = lpSvr;lpSvr->Start();while(true){std::this_thread::sleep_for(std::chrono::seconds(6)); }lpSvr->Stop();lpFac->Stop();mynet::DestroyFactory(lpFac);return 0;
}
后续待处理事项
1.完善各类场景单元测试
2.支持epoll的et模式事件分发
3.制作规范清晰的使用文档
开源地址
1.https://github.com/xubenhao/mynet
2. https://gitee.com/xubenhao2/mynet
相关文章:
mynet开源库
1.介绍 个人实现的c开源网络库. 2.软件架构 1.结构图 2.基于event的自动分发机制 3.多优先级分发队列,延迟分发队列 内部event服务于通知机制的优先级为0,外部event优先级为1. 当集中处理分发的event_callback时,…...
深度挖掘商品信息,jd.item_get API助您呈现商品全面规格参数
深度挖掘商品信息,特别是在电商平台上,对于商家、开发者和用户来说都至关重要。jd.item_get API作为京东开放平台提供的一个强大工具,能够帮助用户轻松获取商品的全面规格参数,进而为商品分析、推荐、比较等提供有力的数据支撑。 …...
A Random Walk Based Anonymous Peer-to-Peer
一、 背景 匿名性一直是P2P系统等自组织环境中最具挑战性的问题之一。在本文中,我们提出了一个匿名协议,称为基于随机漫步的匿名协议(RWAP),在分散的P2P系统。我们通过全面的轨迹驱动模拟来评估RWAP。结果表明,与现有方法相比,RWAP显著降低了流量成本和加密开销。 二、 …...
php代码执行计划任务dos实现方式和宝塔面板实现方式
dos php 计划任务 echo off :loop echo 这是一个死循环 echo This is an infinite loop. php think gpt php think ai timeout /t 2 goto loop 宝塔面板 php 计划任务 #!/bin/bash PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH ste…...
千万不要错过这6款能让你快速写作成长的宝藏软件…… #学习方法#AI写作
国外ChatGPT爆火,AI写作在国内也引起不小的瞩目,目前国内的AI写作工具少说也有几十上百个,要在这么多AI写作中找出适合自己的工具,一个一个尝试是不太现实的,所以今天就给大家推荐一些款AI写作工具。帮助你少走弯路&am…...
TypeScript系列之-理解TypeScript类型系统画图讲解
TypeScript的输入输出 如果我们把 Typescript 编译器看成一个黑盒的话。其输入则是使用 TypeScript 语法书写的文本或者文本集合。 输出是编译之后的 JS 文件 和 .d.ts 的声明文件 其中 JS 是将来需要运行的文件(里面是没有ts语法,有一个类型擦除的操作)࿰…...
制造业智能化一体式I/O模块的集成与应用案例分享
在现代制造业中,智能化一体式I/O模块的应用已经成为提升生产效率、优化工艺流程的关键技术之一。这种一体化I/O模块的主要功能在于作为PLC(可编程逻辑控制器)系统的扩展接口,以满足多样化的输入输出需求。本文将通过一个实际案例&…...
《云原生安全攻防》-- 云原生应用风险分析
为了满足每位朋友的学习需求,并且支持课程的持续更新,本系列课程提供了免费版和付费视频版两种方式来提供课程内容。我们会持续更新课程内容,以确保内容的度和实用性。 在本节课程中,我们将一起探讨云原生应用在新的架构模式下可能…...
抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域,
抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域,让加到私域的粉丝买单 抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 课程内容: 01.第一…...
外包干了6天,技术明显进步
先说一下自己的情况,本科生,2019年我通过校招踏入了南京一家软件公司,开始了我的职业生涯。那时的我,满怀热血和憧憬,期待着在这个行业中闯出一片天地。然而,随着时间的推移,我发现自己逐渐陷入…...
上传应用程序到苹果应用商店的工具和要
引言 在今天的移动应用市场中,将应用程序上传到苹果应用商店(App Store)是许多开发者的首要任务之一。然而,不同操作系统下的开发者可能需要使用不同的工具和遵循不同的要求来完成这一任务。本文将介绍在 macOS、Windows 和 Linu…...
vue:判断当前日期时间是否在一个日期时间区间里
在前端,可以使用 JavaScript 的 Date 对象来判断当前日期时间是否在一个日期时间区间内。 // 定义开始时间和结束时间 const startTime new Date(2024-03-29T08:00:00); // 开始时间 const endTime new Date(2024-04-02T18:00:00); // 结束时间// 获取当前时间 c…...
浏览器禁用cookie后session还能用吗?
1.背景 最近有朋友问我其面试时遇到的一个不常见的问题:浏览器禁用cookie后session还能用吗?,怎么解答。 2.cookie与session联系入手 2.1 理论基础 一般默认情况下,在会话中,服务器存储 session 的 sessionid &…...
C语言——顺序表
文章目录 一、线性表二、顺序表顺序表和数组的区别顺序表的分类1.静态顺序表2.动态顺序表 三、动态顺序表的实现1.动态顺序表头文件2.动态顺序表源文件3.测试源文件 一、线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是⼀种…...
CentOS7安装Docker及禅道
https://blog.csdn.net/weixin_46453070/article/details/136183615?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171246925816800222886233%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id171246925816800222886233&biz_i…...
如何在社交媒体中使用增强现实来提高客户参与度?
目录 1. 增强现实在社交媒体中的应用是如何发展的 2. 社交媒体营销和广告中的增强现实 3. 社交媒体上的增强现实滤镜和镜头 4. 社交媒体平台上的增强现实购物 5. 利用社交媒体的增强现实事件和品牌激活 6. 增强现实在社交媒体中的未来是什么 7. 社交媒体中的增强现实常见…...
Autodesk AutoCAD 2025 (macOS, Windows) - 自动计算机辅助设计软件
Autodesk AutoCAD 2025 (macOS, Windows) - 自动计算机辅助设计软件 AutoCAD 2024 开始原生支持 Apple Silicon,性能提升至 2 倍 请访问原文链接:https://sysin.org/blog/autodesk-autocad/,查看最新版。原创作品,转载请保留出处…...
买卖股票的最佳时机III
题目链接 买卖股票的最佳时机III 题目描述 注意点 1 < prices.length < 1000000 < prices[i] < 100000不能同时参与多笔交易(必须在再次购买前出售掉之前的股票)最多可以完成 两笔 交易 解答思路 本题最多可以完成两笔交易,…...
fastlio2 保存每帧的点云和每帧的里程计为单独的文件做后端回环优化和手动回环优化
为了 提供数据做后端回环优化和手动回环优化,需要保存每帧的点云和每帧的里程计为单独的文件,并且需要保存的名字为ros时间戳。 效果很好,比我自己写的手动回环模块好用 // This is an advanced implementation of the algorithm described in the // following paper: /…...
【线段树】【前缀和】:1687从仓库到码头运输箱子
本题简单解法 C前缀和算法的应用:1687从仓库到码头运输箱子 本文涉及的基础知识点 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 线段树 LeetCode1687从仓库到码头运输箱子 你有一辆货运卡车,你需要用这一辆车…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
