架构总览
客户端
TCP/IPv4
→
epoll Reactor
单线程
→
HTTP 解析
GET/Content-Length
→
线程池队列
文件 I/O
Worker 线程
→
完成队列 + eventfd
→
Reactor 发送响应
→
客户端
设计要点:Reactor 是唯一操作 Socket 和 epoll_ctl 的线程。 Worker 只读取已验证的静态文件并构造响应,结果通过 eventfd 唤醒 Reactor。 连接世代 ID + 请求 ID 防止 fd 复用时旧结果落到新连接上。

运行时状态

事件模型epoll LT / ET
监听端口本机 8080 · 公网 80 / 443
工作线程2
完成通知eventfd
优雅退出SIGINT / SIGTERM

已实现能力

非阻塞 Socket✓
HTTP/1.1 GET✓
HTTPS / TLS 1.2+✓
keep-alive 持久连接✓
400 / 404 / 500✓
路径穿越防护✓

高峰期不卡顿

上百人同时访问也互不拖慢——慢的连接不会影响别人。背后是 epoll 非阻塞 I/O(LT/ET 双模式)。

越用越快

连接用完不立即断开,下一次请求直接复用、免去重复握手。实测吞吐提升约 3 倍(keep-alive)。

传输全程加密

支持 HTTPS,数据在网络上不可被窃听、篡改(TLS 1.2+,浏览器地址栏小锁标志)。

重活后台干

大文件与网络探测交给后台线程处理,不耽误接待新访客(线程池 + eventfd 完成通知)。

什么设备都能用

手机、平板、电脑打开同一个网址即可,还能自动识别并区分不同设备(HTTP/HTTPS 双端口)。

抗折腾

半途断开、恶意请求、超大报文都会被安全处理,服务不中断(请求校验 + 防护限制)。

全程留痕

每次访问、每次检测、每次异常都有日志记录,出了问题可以回溯(结构化 KV 日志)。

配置即改即用

端口、线程数、监控密码写在配置文件里,改完重启生效,不用动一行代码(server.conf)。

改坏有报警

自动化测试覆盖核心流程,每次改动都跑回归验证,质量有保障(CTest 6/6 · ASan/UBSan)。

这个页面在讲什么:实施路线是奕链引擎本身的建造时间线—— 按顺序讲述它怎样从一个最简单的 socket 程序,逐步长出 epoll 事件循环、HTTP 解析、 线程池、TLS 与 keep-alive,每一步做了什么、用什么方式验证。它不是 「连接主机 / 检查主机」的操作过程;设备如何接入、如何检查,请见 「开发者说明」中的全栈解释与接入指南。
Phase 1
TCP 服务器 — socket/bind/listen/accept/recv/send,单客户端收发与异常断开处理。
Phase 2
epoll 事件循环 — 非阻塞 fd、epoll_create/ctl/wait,LT/ET 双模式实验,100+ 连接稳定。
Phase 3
HTTP 解析 — 请求行/Header/Content-Length 解析,GET、404、400、500 响应。
Phase 4
线程池 — worker 线程、任务队列、互斥锁、条件变量、优雅停止。
Phase 5
工程化 — CMake、config、logger、signal、RAII、统一错误码、单元测试。
Phase 6
性能测试 — 三组对比(同步 / epoll / epoll+线程池),记录 RPS、延迟、CPU、内存。
追加
HTTPS/TLS — 双端口监听、非阻塞 SSL_accept 握手状态机、TLS 1.2+;keep-alive — RFC 7230 持久连接、空闲超时扫描(默认 60s,0 禁用)。
后续
sendfile 零拷贝、静态文件缓存、Docker 部署。
// Reactor 主循环
while (!g_stop_requested) {
  const int ready = epoll_wait(epoll_fd_, events, kMaxEvents, 1000);
  for (int i = 0; i < ready; ++i) {
    if (fd == listen_fd_)        accept_clients();
    else if (fd == completion_fd_) handle_completion_event();
    else                         handle_client_event(fd, events);
  }
}

// Worker 完成后通过 eventfd 通知 Reactor
enqueue_completion({fd, conn_id, req_id, status, std::move(response)});
const uint64_t signal = 1;
write(completion_fd_, &signal, sizeof(signal));
关键约束:worker 绝不直接操作 Socket 或调用 epoll_ctl。所有连接状态变更由 Reactor 单线程完成。

开发者说明

这个网页是怎么来的 · 面向好奇者与开发者

这是什么

奕链 YiLink 是一台用 C++17 从零手写的 Linux 网络服务器。 没有 Web 框架,也没有第三方网络库:从 epoll 原语起步,亲手实现 HTTP 解析、 线程池、TLS 加密与实时监控。你现在看到的这个页面,就是由它直接返回的单文件 HTML,没有任何前端框架与外部依赖;页面上的每一次检测,都是真实发生的网络请求。

它同时也是一个面向数据中心网络的实验与诊断平台:本网址把三件事放在一起—— 引擎本体(奕链)、真实数据中心场景(AIDC:硬件清单 / 设备接入 / 链路诊断)、 数据中心网络实验室(DC-Lab:学习档案 / 光链路排错)。本页按全栈视角解释它们如何协同、如何使用。

一次请求的完整旅程

以你刚才打开本页为例,从敲下网址到看到画面,数据走过了这样一条全链路:

  1. 建立连接:浏览器向服务器发起 TCP 三次握手(走 HTTPS 时还会先完成 TLS 握手)。监听 socket 上的事件由 epoll_wait 返回,Reactor 在 accept_clients() 中接收连接,并把新连接 fd 设为非阻塞后注册进 epoll。
  2. 读取请求:连接上数据到达后触发可读事件,handle_client_event() 循环 recv 字节到该连接的接收缓冲区。epoll 支持 LT 与 ET 两种触发模式,ET 下必须一次读到 EAGAIN。
  3. 解析 HTTP:手写的解析器逐字节解析请求行(方法 / 路径)、Header 与 Content-Length,拼出一个完整的请求对象;畸形报文在这里被拦下并返回 400。
  4. 路由与分派:服务器按路径决定谁来处理:静态页面直接读文件返回;轻量 API 在 Reactor 线程内即时计算;压测、网络探测这类耗时任务则被打包扔进线程池,Reactor 立刻回去接待其他连接。
  5. 后台执行:worker 线程完成任务(比如打开 TCP 连向一台交换机、跑一组压测),但它绝不直接碰 socket——结果连同连接标识一起写入完成队列,并向 eventfd 写一个 1。
  6. 回到 Reactor:主循环被 eventfd 唤醒,在 handle_completion_event() 中取出完成项,由 Reactor 单线程把响应发回给对应的连接,状态变更同样只在这里发生。
  7. 浏览器呈现:响应到达浏览器,HTML 被渲染;页面 JS 再发起若干 JSON 请求填充各项数据。keep-alive 连接在空闲超时前可以继续复用,不必反复握手。
这条链路就是「Reactor + 线程池 + eventfd」模式的全部要点:单线程处理连接状态,多线程处理阻塞任务, 用一个 8 字节的 eventfd 把结果安全送回主循环。

这个网址的完整地图

左侧导航已按「角色任务流」收敛:首屏只留健康总览、光链路预测、排障三个主入口;资产与纳管、诊断与自检、帮助与文档都降到折叠区或后台。主站与监控台在同一部署单元(同一域名、同一登录态、同一账户库),进入监控台不再新开标签页:

这个网址的完整地图
主线页面回答什么问题
工具箱工作台 / 连通性诊断 / 网络接口 / 设备接入 / 光链路预测(监控台)/ 监控台网络通不通、快不快、这台机器连了哪些设备
诊断与自检连通性诊断 / 设备监控 / 局域网扫描 / 性能测试(默认收起)排障辅助与演示型检查,不占首屏
项目档案架构总览 / 核心特性 / 实施路线 / 核心代码 / 开发者说明它内部怎么实现、跑多快、按什么顺序建成
帮助与文档学习档案(默认收起,静态资料,非实时探测)数据中心网络怎么学、报文长什么样

API 端点索引

所有端点由同一个 C++ HTTP 解析器直接处理,无框架。证据列标注数据来源:实时 = 当前机器真实读取,登录 = 需要主机视角会话。

API 端点索引
方法路径权限作用证据
GET/公开返回单文件前端 HTML实时
GET/ping公开延迟测试(RTT)实时
GET/health公开服务健康与启动时间实时
GET/api/links公开网络接口状态(admin/carrier/speed/duplex/mtu)实时 · /sys/class/net
GET/api/optics公开光模块 EEPROM 与 DDM(仅物理主机)实时 · ethtool
POST/api/lan/scan登录局域网设备发现(ARP + ping 扫描 + OUI)实时 · /proc/net/arp
GET/api/benchmark公开epoll 性能基准(5 种模式对比)实时 · 回环压测
POST/login公开主机视角登录(monitor_password)实时
POST/logout公开退出登录实时
POST/pair/generate登录生成 6 位配对码实时
POST/pair/revoke登录撤销配对码实时
GET/monitor登录主机视角会话验证实时
超时行为:耗时端点(/api/lan/scan、/api/benchmark)走 deferred task 线程池, 客户端应设置 30–90 秒超时;其它端点均在 Reactor 线程内即时返回(< 10ms)。

接入指南(一):设备如何接入奕链

「主机视角」是本平台的设备组织模型:一台主机作为主控台,其他设备通过配对码加入它。

  1. 创建主机视角:在主机上打开本页,先在顶部登录账户(电话/邮箱),再点击「登录主机视角 → 创建新的主机视角」,已登录账户直接授权创建,无需输入监控密码。成功后得到 24 小时有效的会话 cookie,本设备即成为主控台。
    未登录账户仍可用 config/server.conf 中 monitor_password 的密码创建(后备路径)。
  2. 生成配对码:主控台在「主机视角」页发起配对,服务器生成一个 6 位数字配对码,5 分钟内有效、一次性使用。
  3. 设备加入:新设备打开同一个网址,点击「登录主机视角 → 输入配对码加入」,输入 6 位码。它还会带上自己的设备标识(浏览器本地生成的 device id)与自动识别的名称,调用 /pair/claim 完成登记。
  4. 保持在线:加入后的设备定时向 /agent/beat 发送心跳;主控台在 /monitor 中看到所有在线设备,也可以撤销某台设备的接入。
设计上:创建路径只属于主控台;已登录账户直接授权,未登录账户需监控密码(后备);普通设备只需要一个 6 位码,不需要知道密码。

接入指南(二):DC-Lab 实验成果如何接入本网址

DC-Lab 是用 Linux network namespace + FRRouting 搭建的纯软件数据中心网络实验室: Spine-Leaf 拓扑、VXLAN 隧道、EVPN 控制面、多租户 IRB,全部跑在一台机器里。 实验过程中产生的 Markdown 报告、命令记录与 pcap 抓包,按下面的方式组织,「学习档案」页就能直接呈现:

  1. 写阶段报告:每个阶段产出一份 Markdown,放入 datacenter-network-lab/docs/,说明本阶段解决什么问题、怎么验证。
  2. 留存报文证据:关键协议的抓包放入 datacenter-network-lab/captures/,命名体现阶段与协议(如 p8_evpn.pcap)。
  3. 汇总知识库:knowledge/ 下的 build_knowledge_db.py 把各阶段的概念、命令、实测断言、报文路径汇总为 knowledge.json。
  4. 页面自动呈现:「学习档案」页 fetch 这份 JSON,渲染阶段卡片;Markdown 报告通过页内阅览器直接排版显示,pcap 可点击下载用 Wireshark 打开。
想接入自己的实验成果,不需要改前端:按同样结构补充 Markdown、pcap 与 knowledge.json 条目即可。 更多学习文稿持续整理中,后续文稿都会以页内 Markdown 阅览的方式加入。

接入指南(三):AIDC 真实硬件与设备如何接入

AIDC 三页分别对应数据中心现场的三类工作,全部基于真实读取与真实连接,没有模拟数据:

  • 硬件清单(资产盘点):直接读取运行服务主机的 /proc/cpuinfo、/proc/meminfo、/sys/class/net、/proc/net/arp 等系统文件,得到 CPU、内存、网卡、MAC、ARP 邻居与默认网关。把服务部署到哪台主机,盘点的就是哪台主机。
  • 设备接入(识别网络设备):输入交换机 / 路由器的管理 IP,服务器对其 22(SSH)与 23(Telnet)端口发起真实 TCP 连接,抓取登录横幅(banner),按特征识别华为 VRP、H3C Comware、Cisco IOS、Juniper 等厂商。无需账号密码,不改动设备配置。
  • 链路诊断(分段排障):按「网卡 → 默认网关 → 公网 DNS」的顺序逐段探测,哪一步断,问题就在哪一段。
  • 光链路(热插监控):通过 /sys/class/net 与 ethtool EEPROM 监测接口 UP/DOWN、速率与光模块 DDM 信息。物理网线与光模块的具体接入方式见「光链路排错」页顶部的操作说明。
WSL2 与物理机的区别:本项目运行在 WSL2 中时,看到的网卡是宿主机映射的虚拟 NIC, 无法接触真实 SFP 光模块笼;光模块 present / DDM 数据只有在裸金属 Linux 物理主机上部署时才能读到。 这一区别会如实显示,不会用假数据填充。

在自己的机器上运行

需要 Linux 环境(物理机、虚拟机或 WSL2 均可)、CMake 与 OpenSSL 开发库:

cmake -B build
cmake --build build
./build/tcp_server 8080 --tls

启动后 HTTP 监听 8080;直接运行时可加 --tls 用自签证书在 8443 提供 HTTPS (浏览器会提示证书不受信任)。云端部署则由前置 Nginx 在 443 上终结 TLS, 证书来自 Let's Encrypt,浏览器无警告。 端口、线程数、监控密码、keep-alive 等配置项集中在 config/server.conf, 文件内有逐项注释,改完重启生效,无需改代码。日志写入 logs/。

源码地图与扩展点

  • src/:服务器主体(Reactor、HTTP 解析、路由、监控、配对、压测调度均在此);include/:头文件。
  • tests/:CTest 集成测试,覆盖核心请求流程;scripts/:压测脚本、故障注入、benchmark 工具。
  • docs/:版本验收报告;www/:本网页静态文件;datacenter-network-lab/:实验室环境与成果。
  • 加一个新 API:在 src/tcp_server.cpp 的路由分派处增加路径与处理逻辑(耗时任务走 submit_deferred_task)。
  • 加一个新页面:在 www/index.html 增加一个 .panel、在侧边栏加一个 .tab、并在 viewTitles 映射中登记,三处即可。

附录:HTTP API 速查

API 是理解系统的结果,不是使用系统的入口——先读懂上面的全链路,再看这张表。 除标注 POST 外均为 GET,返回 JSON:

  • 基础:/ping · /health · /ip · /headers · /connections
  • 链路体验:/speed/download?size=N · /speed/upload · /probe/tcp?host=H&port=P · /probe/http?host=H
  • 主机与网络:/netdev · /netstat · /api/links · /api/optics · /api/targets · /api/status · /api/metrics · /api/history
  • AIDC:/hwinfo · /probe/device?host=H
  • 设备与配对(POST 为主):/login · /pair/offer · /pair/claim · /pair/revoke · /agent/beat · /monitor
  • 性能实测:POST /api/benchmark(需主控台登录,约 30 秒返回五组模式数据)

DC-Lab 数据中心网络 · 学习档案

静态学习资料,非实时探测结果 · 内容读取自知识库,售前请以监控台实际数据为准

自主学习成果总览

10 个阶段 · 167 项实测断言全部通过 · 每阶段含概念/命令/实测/报文证据

AIDC 网络工程师知识体系

13 大分支 · 涵盖 DC-Lab 基础 + AIDC 全链路(RDMA / InfiniBand / RoCE / 无损网络 / GPU 互联 / 集合通信 / 集群设计 / 监控调优)· 点击节点查看「必须理解 / 必须观察 / 必须验证」四列表

点击左侧知识节点查看详细要求。

学习过程

十个阶段依次在解决什么问题 · 点击任意节点展开下方对应阶段档案

学习文稿

Markdown 原文 · 点击在页内直接排版阅览
更多学习文稿持续整理中:后续以 Markdown 提供的学习笔记,会经梳理串通后加入此处, 并配以时间轴与动态示意,保持「读得下去、能跟着做」的阅读体验。

阶段档案

展开查看每阶段的概念 / 命令 / 实测观察 / 报文结构

AIDC 动画演示专区

RDMA 通信 · RoCEv2 封装 · AllReduce Ring · PFC/ECN 拥塞控制 · 逐帧动画 + SVG 拓扑演示
专区说明:以下动画演示用于理解 AIDC 网络的核心流程——从 GPU 显存到远端内存的完整路径、 RoCEv2 帧的逐层封装、AllReduce Ring 算法的梯度同步过程、以及 PFC/ECN 拥塞控制闭环。 每个流程都有 SVG 动态拓扑图和逐帧讲解,点击步骤切换帧。

光链路 · 硬件热插排错

插入光模块 / 光网线即自动识别 · 数据来自 /sys/class/net 与 ethtool EEPROM
本页只做实时快照(当前有没有读数、UP/DOWN、DDM 现值)。趋势预测、ETA 与四层证据回溯在 监控台 · 光链路预测工作台; 本页不重复提供第二套预测结论。
实时监测中 轮询间隔 3s

本页「光链路」管的范围

主机网卡口 ↔ 对端交换机 / 路由器之间的那一段物理连接:光纤(SFP/QSFP 光模块 + 双芯光纤)或电口(RJ45 双绞线)。
验证的是:模块插没插、光功率正不正常、速率协没协商、VLAN 通不通、到网关这一跳活没活 —— 即「线插进去以后,这一跳是否成立」。

不要与 AIDC 页搞混

AIDC「设备接入」走的是管理通道:用网线连通交换机/路由器的管理 IP,再从上层 SSH/扫描去管理整组数据中心设备。
简单记:本页看「这根光纤/网线本身」,AIDC 看「接上线之后去管理谁」。两处一个向下看物理跳、一个向上做管理面。

教学 教学演示台 · 链路故障分层定位 预置正常 / 故障场景,随时播放;纯教学演示,不产生任何真实探测流量 TD-00000000-0000 未开始
1模块在位
2光功率
3速率协商
4VLAN
5MAC 表
6STP
7LACP
8ARP
9直连路由
10动态路由
11MTU
12TCP/TLS
13DNS/HTTP
点击上方场景按钮开始演示;小兔子代表一个数据包,光点表示链路上的数据流,沿 模块→光纤→接入交换→Trunk→网关→路由 逐跳到达服务器 B。
点击一个场景开始;演示到的每一步都会在这里用白话解释「这步在查什么、为什么能 / 不能过」。
实测 实机测试台 · 当前主机真实链路体检 仅在检测到真实物理链路 UP 后才可开始;点击后逐项实测,报告直接固定在本位置
🔒 等待真实链路接入

本测试台只对真实物理链路开放。请在本机网卡插入光纤 / 网线并使链路 UP(可看上方面板的实时状态);
检测到 UP 的物理接口后会自动解锁。这里不提供任何模拟选项,也不做教学演示。

物理接口与光模块

全部链路

名称 / 状态 / 速率 / 双工 / MAC
全部链路
接口类型链路速率双工MAC

物理 / 虚拟判定口径:后端以 /sys/class/net/<iface>/device 符号链接是否存在为准, 前端再叠加 MAC OUI(首字节本地管理位 0x02 置位即非厂商烧录地址);虚拟接口不标注物理速率 / 双工。

光功率趋势

后端 60 秒采样 · 保留 14 天 · 线性拟合仅作趋势参考

等待首次采样…

说明:RX / TX 取光模块 DDM 实测值,读不到时记为空值并按断线绘制,不做插值补齐。

事件日志

接入 / 拔出 / 链路建立断开 / 光模块变化

等待硬件事件…

如何把链路接进来测试

先明确监测对象:本页监测的是运行奕链服务的那台主机上的网络接口。 物理 Linux 主机上是真实的 RJ45 / SFP 口;在 WSL2 中运行时看到的是映射的虚拟网卡, 能反映链路 UP/DOWN 与速率,但读不到真实光模块信息。
四个接入场景(默认折叠 · 点击展开)

场景一:插一根电口网线(双绞线)

  1. 准备:主机的 RJ45 网卡、一根完好的双绞线,对端可以是交换机口、家用路由器或另一台电脑。
  2. 插入:水晶头对准卡口推入,听到「咔哒」一声即锁定,两端都要插紧。
  3. 看结果:3 秒内事件日志出现链路 UP;对应接口状态变绿,速率显示协商结果(如 1000 Mb/s)、双工为 full;网卡指示灯同步亮起。
  4. 没 UP 怎么办:依次检查对端口是否启用、水晶头是否压好、线缆是否插紧。现代网卡支持 Auto-MDIX,直通 / 交叉线一般都能自适应。
  5. 拔出:按住水晶头弹片再拔;事件日志会记录链路 DOWN。

场景二:把主机接到一台交换机

  1. 物理拓扑:主机网卡 → 交换机任意业务口(不是管理口也可以,业务口负责承载流量)。插好后先在本页确认物理层 UP、速率与对端口匹配。
  2. 识别设备:切到 AIDC「设备接入」,输入交换机管理 IP(主机必须能路由到该管理网段),通过 SSH/Telnet 横幅识别厂商型号,无需账号密码。
  3. 验证连通:切到「链路诊断」执行一键排查,按 网卡 → 网关 → 外网 逐段确认。
物理口 UP 但业务不通,最常见原因是交换机口的 VLAN 配置不匹配(access VLAN 不一致、 该配 trunk 的配成 access 等)。本页能验证物理与 IP 层,VLAN / 端口配置需要登录交换机核对。

场景三:接入集成组网(多设备、多链路)

  1. 逐台接入:按场景二的方式先识别每一台交换机,确认厂商与管理可达。
  2. 逐链验证:每插好一条线,先在本页事件日志确认 UP 再插下一条——一次只变动一条链路,出问题时才能准确定位。
  3. 端到端验证:全部接完后用「链路诊断」逐段检查;跨设备的路由、VXLAN 隧道与 EVPN 属于配置面,可在「学习档案」中对照概念与命令。
  4. 变更留痕:拔线、换口都会实时写入事件日志,排障时按时间顺序回看即可。

场景四:光模块与光纤(仅物理主机)

  1. 前提条件:裸金属 Linux 主机、网卡带 SFP / SFP+ 笼、光模块规格与口速率匹配(如 10GbE 口配 SFP+)、网卡驱动支持 EEPROM 读取。
  2. 插入模块:去掉模块防尘帽,模块卡扣朝外、金手指朝下推入 SFP 笼,按到底直到锁定。
  3. 接入光纤:拔去光纤头防尘帽,LC 双芯按 TX / RX 对应插入(收发接反则链路不亮),对端同样接好。
  4. 看结果:页面出现光模块卡片,显示 present、协商速率与 DDM 数字诊断(收 / 发光功率、温度、电压、偏置电流);事件日志记录模块接入与链路 UP。
  5. 异常判断:接收光功率过低或为 0 → 对端发光异常、链路衰耗过大或 TX/RX 接反;完全无光 → 光纤未插紧或断纤。
  6. 拔出顺序:先拔光纤,再掰开模块卡扣取下模块,最后盖回防尘帽。光模块支持热插拔,但应避免频繁拔插。
在当前 WSL2 环境中无法验证光模块分支;把服务部署到带 SFP 笼的物理 Linux 主机后, 以上模块卡与 DDM 数据才会出现。此处不使用任何模拟光模块数据。