4.IO多路复用-select
IO多路复用IO 多路复用是一种让单个线程(或少量线程)能够同时监听多个文件描述符(File Descriptor,FD,比如网络连接、文件、管道)的技术,当某个 FD 有可读 / 可写事件发生时,系统会通知程序去处理对应的 IO 操作。 它解决的核心问题是:避免线程 / 进程阻塞在单个 IO 操作上,提升程序处理大量并发 IO 的能力(比如高并发的服务器)。 IO 多路复用的三种核心实现(Linux 下) 方式 特点 适用场景 select 监听的 FD 数量有限(默认 1024),每次调用需要拷贝 FD 集合,效率低 兼容性好,低并发场景 poll 突破 FD 数量限制,但仍需遍历所有 FD,高并发下效率一般 中等并发,需要兼容多系统 epoll 基于事件驱动,只处理有事件的 FD,无 FD 数量上限,效率最高 高并发场景(如百万连接) select函数原型select 是 IO 多路复用的基础实现,内部基于线性表实现的,核心作用是委托内核批量检测多个文件描述符(fd)的读写 / 异常状态,且具备跨平台特性(Linux...
3.端口复用
端口复用一、端口复用解决了什么问题?在讲解具体用法前,先明确端口复用的核心价值 —— 它主要解决两类高频的 “端口占用” 问题: 问题 1:服务重启时提示 “Address already in use” 默认情况下,当你关闭一个 TCP 服务端(比如 epoll 服务)后,端口不会立即释放,而是会进入 TIME_WAIT 状态(通常持续 2-4 分钟)。此时如果立即重启服务,内核会提示: 1bind failed: Address already in use 这是因为内核认为该端口还被 “旧连接” 占用,不允许新进程绑定。 问题 2:多进程 / 多线程绑定同一端口(如负载均衡) 某些场景下(比如 Nginx 多进程、多线程服务),需要让多个进程 / 线程同时监听同一个端口,默认情况下内核会拒绝,而端口复用可以允许这种操作。 二、端口复用的核心原理端口复用的核心是设置套接字选项 SO_REUSEADDR,它会修改内核对 TCP 端口的绑定规则: 允许绑定处于 TIME_WAIT 状态的端口:跳过 “端口被 TIME_WAIT 连接占用” 的检查; 允许多...
2.socket编程
这篇文章讲了 socket 编程的基础流程,包括客户端和服务端的交互过程 socket编程 通信测试代码服务端1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283#include<unistd.h> // 提供read/write/close等系统调用#include<stdio.h> // 标准输入输出#include<stdlib.h> // 标准库(exit等)#include<string.h> // 字符串操作(memset等)#include<stdint.h> // 整型类型(uint16_t等)#include<arpa/inet.h> // 网络编程(inet_ntop/ht...
1.字节序和IP地址转换
字节序1. 字节序是什么?(通俗理解)字节序(Endianness)指的是多字节数据在内存中的存储顺序。 计算机存储数据时,单个字节(如 0x12)没有顺序问题,但多字节数据(如 16 位端口号 0x1234、32 位 IP 地址 0x12345678)会有两种存储方式: 把高位字节存在低内存地址(大端) 把低位字节存在低内存地址(小端) 1. 大端序(Big-Endian):“高位在前”(符合人类习惯) 规则:高位字节存在低地址内存格,低位字节存在高地址内存格; 比喻:像人类写数字 1234 一样,先写高位的12,再写低位的34; 例子:存储 0x1234(十进制 4660) 内存地址 存储内容 说明 100 0x12 低地址存高位字节 101 0x34 高地址存低位字节 2. 小端序(Little-Endian):“低位在前”(计算机更常用) 规则:低位字节存在低地址内存格,高位字节存在高地址内存格; 比喻:把数字倒着写,先写低位的34,再写高位的12; 例子:存储 0x1234(十进制 4660) 内存地址 存储内容 说明 1...
11.enable_if
enable_if一、std::enable_if 核心定义std::enable_if 是 C++11 引入的模板元编程工具,本质是条件编译模板,核心作用是: 根据一个编译期布尔条件,决定是否 “启用” 某个模板(函数 / 类); 底层完全依赖 SFINAE 规则:条件为 false 时,enable_if 的 type 成员不存在 → 模板替换失败,编译器跳过该版本;条件为 true 时,type 存在 → 模板正常启用。 官方定义(简化版)1234567891011template <bool B, typename T = void>struct enable_if {}; // 条件B为false时,无type成员template <typename T>struct enable_if<true, T> { // 条件B为true时,定义type成员 using type = T;};// 常用别名(简化写法)template <bool B, typename T ...
10.SFINAE
SFINAE一、SFINAE 核心定义SFINAE 直译是「替换失败不是错误」,是 C++ 模板重载解析阶段的关键规则: 当编译器尝试将模板参数替换为具体类型时,如果出现 “语法合法但替换失败” 的情况,不会直接报错,而是跳过这个模板重载版本,继续尝试其他可行的版本; 只有当所有模板重载版本都替换失败,且无其他非模板重载可用时,编译器才会抛出真正的编译错误。 通俗理解(无比喻版)模板重载就像 “多套备用方案”,编译器会逐个检查方案是否适配当前类型: 某套方案因类型不匹配导致替换失败 → 放弃这套方案,看下一套; 所有方案都适配失败 → 才报错。 二、核心原理:模板替换阶段 vs 编译阶段SFINAE 只作用于模板参数替换阶段,而非后续的语义分析 / 编译阶段,这是关键: 阶段 行为 SFINAE 是否生效 模板参数替换阶段 编译器将实参类型代入模板形参,检查语法是否合法(如成员是否存在、类型是否匹配) 生效(失败则跳过) 语义分析 / 编译阶段 检查代码逻辑(如变量未定义、函数调用错误) 不生效(直接报错) 三、SFINAE 的典型...
9.模板折叠
模板折叠(Fold Expressions)1. 折叠表达式的概念与背景在C++中,可变参数模板允许函数或类模板接受任意数量的模板参数。这在编写灵活且通用的代码时非常有用。然而,处理参数包中的每个参数往往需要递归模板技巧,这样的代码通常复杂且难以维护。 折叠表达式的引入显著简化了这一过程。它们允许开发者直接对参数包应用操作符,而无需手动展开或递归处理参数。这不仅使代码更加简洁,还提高了可读性和可维护性。 C++17 折叠表达式的分类依据是参与折叠的参数包数量,而非操作符的元数: 折叠表达式可分为: 一元折叠(Unary Fold):仅针对单个参数包,通过一个二元操作符将参数包中的所有元素按指定结合方向 “串联” 成连续表达式,无需额外固定值参与运算。 二元折叠(Binary Fold):针对 “一个参数包 + 一个额外固定值”,通过同一个二元操作符将固定值与参数包元素按指定结合方向串联成连续表达式,是一元折叠的扩展(解决带初始值的运算场景)。 一元操作符(!/~/++ 等)无法直接作为折叠表达式的 op,因为折叠的本质是 “将参数包的元素用操作符串联起来”...
8.模板特例化
模板特化(Template Specialization)模板特化允许开发者为特定类型或类型组合提供专门的实现。当通用模板无法满足特定需求时,特化模板可以调整行为以处理特定的情况。C++ 支持全特化(Full Specialization)和__偏特化(Partial Specialization),但需要注意的是,函数模板不支持偏特化,只能进行全特化 类模板的特例化类模板全特化123456789101112131415template<typename T> class Printer { public: void print(const T& obj) { std::cout<<"General Printer "<<obj<<std::endl; } }; template<> class Printer<std::string> { public: void p...
7.奇异递归模板(CRTP)
奇异递归模板(CRTP)一、什么是 CRTP?奇异递归模板模式(Curiously Recurring Template Pattern)是 C++ 中的一种高级模板技巧,核心特征是:一个类派生自以自身作为模板参数的基类。 代码实例 12345678910111213141516171819// 基类:模板类,接收派生类作为模板参数template <typename Derived>class Base {public: // 基类中可调用派生类的成员 void interface() { // 向下转型为派生类(安全,因为Derived必然是子类) static_cast<Derived*>(this)->implementation(); }};// 派生类:继承基类,且将自身作为基类的模板参数class Derived : public Base<Derived> {public: // 派生类实现具体逻辑 void imp...
6.stl常用函数
一、通用基础函数(几乎所有容器都支持)这些函数是所有容器的共性,是使用 STL 容器的基础: 函数 功能说明 empty() 判断容器是否为空,返回bool值(空返回true),时间复杂度 O (1) size() 返回容器中元素的个数,时间复杂度 O (1)(list/forward_list 除外,O (n)) clear() 清空容器中所有元素,释放内存(不同容器释放策略略有差异) begin() 返回指向容器第一个元素的迭代器(可读可写,非 const 容器) end() 返回指向容器末尾之后的迭代器(尾后迭代器,不可解引用) cbegin()/cend() 返回只读的 const 迭代器(不能通过迭代器修改元素) swap() 交换两个同类型容器的内容,时间复杂度 O (1)(底层交换内部指针,效率极高) 示例(通用函数): 1234567891011121314151617181920#include <iostream>#include <vector>using namespace...