从零开始实现一个C++高性能服务器框架----Socket模块
此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善
项目地址:https://gitee.com/lzhiqiang1999/server-framework
简介
项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。
详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。
Socket模块
1. 主要功能
- 对Linux下socket相关方法的封装,包括bind、listen、connect、read/write系列等方法。
- 支持快速创建TCP、UDP对应的Socket。
2. 功能演示
- 模拟一个请求百度的客户端,并打印出响应
IPAddress::ptr addr = Address::LookupAnyIPAddress("www.baidu.com:80");
// 创建socket
Socket::ptr socket = Socket::CreateTCP(addr);
// 连接
socket->connect(addr);
//发送数据
const char buf[] = "GET / HTTP/1.1\r\n\r\n";
int rt = socket->send(buf, sizeof(buf));
if(rt <= 0) {LOG_INFO(g_logger) << "send fail";return;
}//接收数据
std::string buffers;
buffers.resize(4096);
rt = socket->recv(&buffers[0], 4096);
if(rt <= 0) {LOG_INFO(g_logger) << "recv fail";return;
}LOG_INFO(g_logger) << buffers;
3. 模块介绍
3.1 Socket
- 对socket相关方法的封装,包括以下内容
- 创建各种类型的套接字对象的方法(TCP套接字,UDP套接字,Unix域套接字)
- 设置套接字选项,比如超时参数
- bind/connect/listen方法,实现绑定地址、发起连接、发起监听功能
- accept方法,返回连入的套接字对象
- 发送、接收数据的方法
- 获取本地地址、远端地址的方法
- 获取套接字类型、地址类型、协议类型的方法
- 取消套接字读、写的方法
class Socket : public std::enable_shared_from_this<Socket>, Noncopyable{public:typedef std::shared_ptr<Socket> ptr;typedef std::weak_ptr<Socket> weak_ptr;// 创建TCP Socket(满足地址类型)static Socket::ptr CreateTCP(johnsonli::Address::ptr address);// 创建UDP Socket(满足地址类型)static Socket::ptr CreateUDP(johnsonli::Address::ptr address);// 创建IPv4的TCP Socketstatic Socket::ptr CreateTCPSocket();// 创建IPv4的UDP Socketstatic Socket::ptr CreateUDPSocket();// 创建IPv6的TCP Socketstatic Socket::ptr CreateTCPSocket6();// 创建IPv6的UDP Socketstatic Socket::ptr CreateUDPSocket6();Socket(int family, int type, int protocol = 0);virtual ~Socket();int64_t getSendTimeout(); // 获取发送超时时间(毫秒)void setSendTimeout(int64_t v); // 设置发送超时时间(毫秒)int64_t getRecvTimeout(); // 获取接受超时时间(毫秒)void setRecvTimeout(int64_t v); // 设置接受超时时间(毫秒)// 获取sockopt @see getsockoptbool getOption(int level, int option, void* result, socklen_t* len);// 获取sockopt模板 @see getsockopttemplate<class T>bool getOption(int level, int option, T& result) {socklen_t length = sizeof(T);return getOption(level, option, &result, &length);}// 设置sockopt @see setsockoptbool setOption(int level, int option, const void* result, socklen_t len);// 设置sockopt模板 @see setsockopttemplate<class T>bool setOption(int level, int option, const T& value) {return setOption(level, option, &value, sizeof(T));}/*** @brief 接收connect链接* @return 成功返回新连接的socket,失败返回nullptr* @pre Socket必须 bind , listen 成功*/virtual Socket::ptr accept();/*** @brief 绑定地址* @param[in] addr 地址* @return 是否绑定成功*/virtual bool bind(const Address::ptr addr);/*** @brief 连接地址* @param[in] addr 目标地址* @param[in] timeout_ms 超时时间(毫秒)*/virtual bool connect(const Address::ptr addr, uint64_t timeout_ms = -1);virtual bool reconnect(uint64_t timeout_ms = -1);/*** @brief 监听socket* @param[in] backlog 未完成连接队列的最大长度* @result 返回监听是否成功* @pre 必须先 bind 成功*/virtual bool listen(int backlog = SOMAXCONN);/*** @brief 关闭socket*/virtual bool close();/*** @brief 发送数据* @param[in] buffer 待发送数据的内存* @param[in] length 待发送数据的长度* @param[in] flags 标志字* @return* @retval >0 发送成功对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int send(const void* buffer, size_t length, int flags = 0);/*** @brief 发送数据* @param[in] buffers 待发送数据的内存(iovec数组)* @param[in] length 待发送数据的长度(iovec长度)* @param[in] flags 标志字* @return* @retval >0 发送成功对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int send(const iovec* buffers, size_t length, int flags = 0);/*** @brief 发送数据* @param[in] buffer 待发送数据的内存* @param[in] length 待发送数据的长度* @param[in] to 发送的目标地址* @param[in] flags 标志字* @return* @retval >0 发送成功对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int sendTo(const void* buffer, size_t length, const Address::ptr to, int flags = 0);/*** @brief 发送数据* @param[in] buffers 待发送数据的内存(iovec数组)* @param[in] length 待发送数据的长度(iovec长度)* @param[in] to 发送的目标地址* @param[in] flags 标志字* @return* @retval >0 发送成功对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int sendTo(const iovec* buffers, size_t length, const Address::ptr to, int flags = 0);/*** @brief 接受数据* @param[out] buffer 接收数据的内存* @param[in] length 接收数据的内存大小* @param[in] flags 标志字* @return* @retval >0 接收到对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int recv(void* buffer, size_t length, int flags = 0);/*** @brief 接受数据* @param[out] buffers 接收数据的内存(iovec数组)* @param[in] length 接收数据的内存大小(iovec数组长度)* @param[in] flags 标志字* @return* @retval >0 接收到对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int recv(iovec* buffers, size_t length, int flags = 0);/*** @brief 接受数据* @param[out] buffer 接收数据的内存* @param[in] length 接收数据的内存大小* @param[out] from 发送端地址* @param[in] flags 标志字* @return* @retval >0 接收到对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int recvFrom(void* buffer, size_t length, Address::ptr from, int flags = 0);/*** @brief 接受数据* @param[out] buffers 接收数据的内存(iovec数组)* @param[in] length 接收数据的内存大小(iovec数组长度)* @param[out] from 发送端地址* @param[in] flags 标志字* @return* @retval >0 接收到对应大小的数据* @retval =0 socket被关闭* @retval <0 socket出错*/virtual int recvFrom(iovec* buffers, size_t length, Address::ptr from, int flags = 0);// 输出信息到流中virtual std::ostream& dump(std::ostream& os) const;virtual std::string toString() const;bool cancelRead(); // 取消读bool cancelWrite(); // 取消写 bool cancelAccept(); // 取消acceptbool cancelAll(); // 取消所有事件protected:void initSock(); // 设置socket属性void newSock(); // 创建socket m_sockfd = socket()virtual bool init(int sock); // 初始化sock,调用initSockprotected: int m_sockfd; /// socket句柄 int m_family; /// 协议簇 int m_type; /// 类型 int m_protocol; /// 协议 bool m_isConnected; /// 是否连接 Address::ptr m_localAddress; /// 本地地址 Address::ptr m_remoteAddress; /// 远端地址};// 流式输出socketstd::ostream& operator<<(std::ostream& os, const Socket& sock);
}
相关文章:
从零开始实现一个C++高性能服务器框架----Socket模块
此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 简介 项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度&am…...
ld: library not found for -lcrt0.o
ld: library not found for -lcrt0.o 背景: Mac 系统编译的时候报错 语言:golang 原因: 代码使用了静态编译,-static。stack overflow 上说 This option will not work on Mac OS X unless all libraries (including libgcc.a…...
接口测试和功能测试的区别有哪些?说一些你不知道的知识
目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 编辑 举个例子 对于接口测试 对于功能测试 编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型,主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...
深度学习实战——不同方式的模型部署(CNN、Yolo)
忆如完整项目/代码详见github:https://github.com/yiru1225(转载标明出处 勿白嫖 star for projects thanks) 目录 系列文章目录 一、实验综述 1.实验工具及及内容 2.实验数据 3.实验目标 4.实验步骤 二、ML/DL任务综述与模型部署知识…...
【论文阅读】GNN阅读笔记
A gentle introduction on gnn 前言 发表在distill的文章 图神经网络在应用上才刚刚开始 搭建了一个GNN playground 什么是图 图是表示实体之间的关系 可以分别表示成点向量、边向量、图向量 图可以分为有向图和无向图 数据是怎么表示成图 图片表示成图: …...
QT常用控件——QTreeWidget(树控件),QTableWidget控件
目录 ★先开个小灶,在此插句话:【有关Halcon与Qt联编变量转换】 QTreeWidget树控件 QTableWidget控件...
为什么学校购买小型数控机床而不是大型工业数控机床?
CNC 机器是计算机控制的设备,可以高精度和准确度地切割、雕刻、钻孔或雕刻各种材料。 它们广泛应用于制造、工程、设计和艺术行业。 CNC 机器具有不同的尺寸和功能,从小型台式机到大型工业机型。 人们可能想知道为什么学校会选择购买小型 CNC 机器而不是…...
【Go自学】一文搞懂Go append方法
我们先看一下append的源码 // The append built-in function appends elements to the end of a slice. If // it has sufficient capacity, the destination is resliced to accommodate the // new elements. If it does not, a new underlying array will be allocated. //…...
【压测】通过Jemeter进行压力测试(超详细)
文章目录背景一、前言二、关于JMeter三、准备工作四、创建测试4.1、创建线程组4.2、配置元件4.3、构造HTTP请求4.4、添加HTTP请求头4.5、添加断言4.6、添加察看结果树4.7、添加Summary Report4.8、测试计划创建完成五、执行测试计划总结背景 通过SpringCloudGateway整合Nacos进…...
C# | 上位机开发新手指南(七)加密算法
上位机开发新手指南(七)加密算法 文章目录上位机开发新手指南(七)加密算法前言加密算法的分类对称加密算法和非对称加密算法流加密算法和块加密算法分组密码和序列密码哈希函数和消息认证码对称加密与非对称对称加密优点缺点对称加…...
实验一 跨VLAN访问
目录 一、按照拓扑图配置VLAN,并实现跨VLAN间的访问。 二、实验环境 三、实验步骤 一、按照拓扑图配置VLAN,并实现跨VLAN间的访问。 1、配置好交换机的VLAN和各个终端的地址,实现各个VLAN内能连通。 2、开启两个交换机的VTY连接࿰…...
通信算法之130:软件无线电-接收机架构
1. 超外差式接收机 2.零中频接收机 3.数字中频接收机...
C++编程大师之路:从入门到精通-C++基础入门
文章目录前言主要内容C基础入门初识C第一个C程序注释变量常量关键字标识符命名规则数据类型整型sizeof关键字实型(浮点型)字符型转义字符字符串型布尔类型 bool数据的输入运算符算术运算符赋值运算符比较运算符逻辑运算符程序流程结构选择结构if语句三目…...
如何在千万级数据中查询 10W 的数据并排序
前言 在开发中遇到一个业务诉求,需要在千万量级的底池数据中筛选出不超过 10W 的数据,并根据配置的权重规则进行排序、打散(如同一个类目下的商品数据不能连续出现 3 次)。 下面对该业务诉求的实现,设计思路和方案优…...
RocketMQ消息文件过期原理
文章目录 消费完后的消息去哪里了?什么时候清理物理消息文件?这样设计带来的好处跳过历史消息的处理所有的消费均是客户端发起Pull请求的,告诉消息的offset位置,broker去查询并返回。但是有一点需要非常明确的是,消息消费后,消息其实并没有物理地被清除,这是一个非常特殊…...
Docker容器理解
目录 目录 一:简单理解操作系统 操作系统: 内核: 内核空间和用户空间: 二:简单理解文件系统 1:什么是文件系统 2:什么是root文件系统 三:docker 1:docker镜像 2&…...
SpringBoot 整合knife4j
文章目录SpringBoot 整合knife4j引入knife4j注解案例knife4j增强功能接口添加作者资源屏蔽访问页面加权控制接口排序分组排序请求参数缓存过滤请求参数禁用调试禁用搜索框SpringBoot 整合knife4j Knife4j是一款基于Swagger 2的在线API文档框架 在Spring Boot中,使…...
73-归并排序练习-LeetCode148排序链表
题目 给你链表的头结点 head ,请将其按升序排列并返回排序后的链表 。 示例 1: 输入:head [4,2,1,3] 输出:[1,2,3,4] 示例 2: 输入:head [-1,5,3,4,0] 输出:[-1,0,3,4,5] 示例 3ÿ…...
Hystrix学习笔记
Hystrix 官方文档: https://github.com/Netflix/Hystrix/wiki 是什么 In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed …...
面向对象编程(基础)8:关键字:package、import
目录 8.1 package(包) 8.1.1 语法格式 说明: 8.1.2 包的作用 8.1.3 应用举例 举例2:MVC设计模式 8.1.4 JDK中主要的包介绍 8.2 import(导入) 8.2.1 语法格式 8.2.2 应用举例 8.2.3 注意事项 8.1 package(包) package,称为包&#x…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...
