从零实现Tracert:原始套接字与ICMP路由跟踪详解
简介一份以计算机网络课程设计为背景的Tracert程序设计报告面向学习原始套接字编程、ICMP协议与路由跟踪原理的学生或开发人员。报告从设计目的出发逐步讲解路由跟踪的工作机制并给出基于Windows Socket API的程序框架与流程分析可帮助读者理解Tracert背后的网络诊断逻辑。资源为独立doc文档仅1个文件大小约194KB内容覆盖实验目的、设计要求、系统详细设计、程序流程图以及关键源代码片段。已有167人学习浏览适合需要完成类似课程作业或希望深入理解tracert命令实现原理的入门及中级学习者。借助这份报告读者不仅能看到Tracert从发送数据包到解析路由器响应的完整过程还能获得原始套接字编程与ICMP报文处理的排错思路为后续网络工具开发打下基础。1. Tracert 程序设计报告一份能直接跑的原始套接字课程设计排查网络故障时ping只能告诉你通不通而tracert能告诉你断在哪一跳。这份课程的计算机网络设计报告正是带你从零实现一个tracert命令的完整源码包Windows 环境下用 VC6.0 编写基于 SOCK_RAW 原始套接字和 ICMP 协议逐跳递增 TTL 并向目标发送回显请求通过解析路由器返回的 ICMP 超时报文还原出数据报从源到目的经过的每一个 IP 地址和往返时延。适合正在做计算机网络课程设计、想搞懂 ICMP 或原始套接字编程的学生也适合想看看 Tracert 底层到底怎么收包解码的开发者。它能直接编译运行也能作为模板改成你自己的路由跟踪小工具。2. 路由跟踪的设计逻辑TTL、ICMP 与原始套接字为什么是这套组合2.1 用 TTL 递减把「路径」变成逐跳回包路由跟踪的核心难题是你根本不知道数据报会经过哪些路由器路由器之间也不会主动给你报信。协议栈给出的答案是 TTLTime To Live字段——IPv4 数据报头部里的一个一字节计数器每经过一个路由器就减 1减到 0 时路由器不再转发而是向源地址回一个 ICMP 超时报文类型 11Time Exceeded报文的源 IP 正好就是这台路由器的接口地址。这就是 tracert 的全部秘密第一次发一个 TTL1 的包第一跳路由器收到后 TTL 减为 0回一个超时报文你读到了第一跳的 IP接着把 TTL 改成 2 再发第一跳正常转发第二跳把 TTL 减到 0回超时报文你读到了第二跳的 IP。如此循环TTL 每递增一次就能「逼」路径上的第 N 个路由器开口说话直到目标主机直接回应或者 TTL 达到上限Windows 的 tracert 默认是 30 跳。这份报告的主循环就是按照这条逻辑走的iTTL从 1 开始每次setsockopt重新设置 IP_TTL发完一个包后iTTL直到bReachDestHost置位或跳数耗尽。2.2 选 ICMP 而不是 UDPWindows 下 tracert 的两种实现路线教材里常讲 traceroute 用 UDP 探测目的是让目标主机回一个「端口不可达」ICMP 类型 3 代码 3来确定到达终点。但 Windows 系统自带的tracert命令默认用的是 ICMP Echo Request也就是和ping同一种报文Linux/macOS 的traceroute默认才是 UDP。这份报告选择了 ICMP 路线有它的现实理由目标主机收到 ICMP 回显请求后会直接回 Echo Reply不需要应用层有对应端口在监听所以对远端设备的适用面更广同时代码里只需要处理 ICMP 一种协议不用额外构造 UDP 头的 checksum课程设计的编码量更可控。带来的代价是解码时要同时处理两种 ICMP 报文中间路由器回的ICMP_TIMEOUT类型 11和目标主机回的ICMP_ECHO_REPLY类型 0。注意recvfrom收到的是一个完整 IP 包不是裸 ICMP 报文所以要先跳过一个 IP 头才能拿到 ICMP 头而为超时报文做解析时报文载荷里还嵌着一个完整的原始 IP 头和原始 ICMP 头用于让你确认这是哪个请求触发的超时得再剥两层才能拿到原始的 id 和 seq。2.3 这份程序的功能框架与输入输出约定从报告正文能提炼出完整的功能边界输入是一个 IP 地址或域名输出是三条关键信息——跳数序号、每一跳的路由器 IP、到达该路由器所需的往返时延。中间路由器不回应时输出*和Request timed out。程序开头还会打印一句Tracing route to ... with a maximum of 30 hops这和 Windows 内置 tracert 的格式几乎一致。程序还把「目的探测」作为隐藏前置功能实现了如果目标主机直接不可达WSAEHOSTUNREACH会在某一跳输出Destination host unreachable并结束如果域名解析失败则直接报错退出。整个程序的输入输出约定可以概括为一张表输入预期输出对应实现位置合法 IP 地址逐跳 IP 与 RTT主循环 DecodeIcmpResponse合法域名先解析为 IP再逐跳探测gethostbyname 分支非法域名Could not resolve the host name参数检查分支不可达目标Destination host unreachablesendto 返回 WSAEHOSTUNREACH 分支3. 逐段拆解 Tracert 源码从 Winsock 初始化到逐跳输出3.1 参数解析、WSAStartup 与原始套接字的创建参数入口main(int argc, char* argv[])先校验命令行参数必须恰好给一个目标地址否则打印用法提示并返回 -1。接着是 Windows Socket 编程的第一步——初始化 WinSock2 环境用WSAStartup请求 2.2 版本的库WSADATA wsa; if (WSAStartup(MAKEWORD(2, 2), wsa) ! 0) { cerr \nFailed to initialize the WinSock2 DLL\n error code: WSAGetLastError() endl; return -1; }MAKEWORD(2, 2)表示要求加载 WinSock 2.2WSADATA会带回实现细节。这一步不做后面所有socket函数都会返回SOCKET_ERROR错误码通常是 10093WSA_NOT_INITIALIZED。然后程序用inet_addr尝试把参数直接转成 32 位 IP如果返回INADDR_NONE说明参数是域名改走gethostbyname解析并顺带打印目标域名和它对应的 IP。原始套接字在这一段创建参数值得逐字看SOCKET sockRaw WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);AF_INET是 IPv4 地址族SOCK_RAW指定原始套接字第三个参数IPPROTO_ICMP声明这个原始套接字只处理 ICMP 协议Windows 对原始套接字有安全限制用IPPROTO_ICMP是当下最稳的合法用法。WSA_FLAG_OVERLAPPED允许套接字支持重叠 I/OWindows 下后续的sendto/recvfrom可以正常工作如果把最后两个参数换成(NULL, 0, 0)也能跑只是少了一个异步扩展能力。3.2 构造 ICMP Echo 请求类型、校验和、序列号发送缓冲区被设计成ICMP_HEADER 32 字节数据的结构ICMP_HEADER是自定义结构体字段依次是type、code、cksum、id、seq。构造分两步先把头部和载荷清零并填好固定字段再单独计算校验和ICMP_HEADER* pIcmpHeader (ICMP_HEADER*)IcmpSendBuf; pIcmpHeader-type ICMP_ECHO_REQUEST; // 类型 8 pIcmpHeader-code 0; pIcmpHeader-id (USHORT)GetCurrentProcessId(); memset(IcmpSendBuf sizeof(ICMP_HEADER), E, DEF_ICMP_DATA_SIZE);type 8表示这是回显请求code 0是回显请求的唯一合法代码。id字段在 Windows 实现里常取进程 ID这样如果同时跑多个 Tracert 程序接收端靠id就能区分是哪个进程的包。载荷填充E只是占位实际内容无所谓路由器只关心头。注意腾出空间放数据和首部所以memset的起始位置跳过了ICMP_HEADER的大小。校验和的计算是 ICMP 编程里最容易错的一步报告里的GenerateChecksum实现是标准算法USHORT GenerateChecksum(USHORT* pBuf, int iSize) { unsigned long cksum 0; while (iSize 1) { cksum *pBuf; iSize - sizeof(USHORT); } if (iSize) cksum *(UCHAR*)pBuf; cksum (cksum 16) (cksum 0xffff); cksum (cksum 16); return (USHORT)(~cksum); }逻辑是把所有 16 位字累加到一个 32 位变量里如果数据长度是奇数最后剩一个字节的低位也要累加然后反复把高 16 位折叠回低 16 位最后取反。要在算校验和之前把cksum字段清零否则会把旧的校验和当成数据一起参与计算结果必然错误。代码在主循环里就是这个顺序((ICMP_HEADER*)IcmpSendBuf)-cksum 0;然后htons(usSeqNo)填序列号最后算 checksum。序列号用来匹配每个 TTL 对应的请求和响应。3.3 TTL 递增主循环发送、等待与超时分支主循环是这份程序最值得抄的部分它用while (!bReachDestHost iMaxHop--)控制整体跳数上限循环体里每次先重新setsockopt设置IP_TTLsetsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char*)iTTL, sizeof(iTTL));IPPROTO_IP表示要改的是 IP 层的选项IP_TTL对应 TTL 字段。这条路走通后同一个 socket 反复发包每轮的 TTL 都不同这是实现 Tracert 的关键技巧——不用重建套接字。如果这段设置失败最常见的原因是权限不足后面避坑章会详细说。发送时需要注意sendto的返回值处理。报告里对WSAEHOSTUNREACH10065做了专门分支打印Destination host unreachable后直接收尾。其他错误码则交给外层统一处理退出。发送成功后进入核心的接收循环while (1) { iReadDataLen recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, 0, (sockaddr*)from, iFromLen); if (iReadDataLen ! SOCKET_ERROR) { if (DecodeIcmpResponse(IcmpRecvBuf, iReadDataLen, stDecodeResult)) { if (stDecodeResult.dwIPaddr.s_addr destSockAddr.sin_addr.s_addr) bReachDestHost TRUE; cout \t inet_ntoa(stDecodeResult.dwIPaddr) endl; break; } } else if (WSAGetLastError() WSAETIMEDOUT) { cout setw(9) * \t Request timed out. endl; break; } ... }注意这里是while (1)内层循环原因在于原始套接字收到的是本机网卡上所有 ICMP 报文不只是你发出的请求所对应的回包如果收到的包解码后不匹配比如别的程序触发的 ICMP 响应就继续recvfrom直到拿到匹配包或超时。超时值由之前setsockopt设置的SO_RCVTIMEO决定默认 3000 毫秒。收到匹配包后如果是目标地址回的置bReachDestHost TRUE下次循环条件不满足就退出不是目标地址回的中间路由器超时报文打印 IP 后 break进入下一跳。3.4 DecodeIcmpResponse 解码两种回包与载荷偏移DecodeIcmpResponse是另一段重点代码它的任务是把收到的原始 IP 包拆成可读信息。第一步是算 IP 头长度IP_HEADER* pIpHdr (IP_HEADER*)pBuf; int iIpHdrLen pIpHdr-hdr_len * 4; if (iPacketSize (int)(iIpHdrLen sizeof(ICMP_HEADER))) return FALSE;IPv4 头部长度字段的单位是 4 字节普通 IP 头固定是 20 字节所以hdr_len通常等于 5乘 4 得 20。先做一次最小长度校验防止后面越界访问。接着按 ICMP 类型分两条路。如果是ICMP_ECHO_REPLY类型 0说明是目标主机的直接回应id 和 seq 就在外层 ICMP 头里直接取if (pIcmpHdr-type ICMP_ECHO_REPLY) { usID pIcmpHdr-id; usSquNo pIcmpHdr-seq; }如果是ICMP_TIMEOUT类型 11路由器返回的超时报文里没有你的请求信息必须去载荷里找原始请求的头这段代码展示了两层偏移的完整写法char* pInnerIpHdr pBuf iIpHdrLen sizeof(ICMP_HEADER); int iInnerIPHdrLen ((IP_HEADER*)pInnerIpHdr)-hdr_len * 4; ICMP_HEADER* pInnerIcmpHdr (ICMP_HEADER*)(pInnerIpHdr iInnerIPHdrLen); usID pInnerIcmpHdr-id; usSquNo pInnerIcmpHdr-seq;第一次偏移外层 IP 头长度 ICMP 头大小跳过 ICMP 头类型 11 报文的头是固定的 8 字节指向被封装在载荷里的原始 IP 头第二次偏移把这个内层 IP 头的长度再加进去才指向原始 ICMP 头。潜在问题是如果内层 IP 头是 20 字节但外层 IP 头带可选字段偏移量会有出入所以标准做法是每次都从字段里读hdr_len而不是写死 20。拿到usID和usSquNo后做双重匹配校验——必须等于当前进程 ID 和当前期望序列号stDecodeResult.usSeqNo否则丢弃。这一步过滤掉了无关 ICMP 流量是整个程序不输出乱数据的保证。校验通过后把当前 IP 头的源 IP 写入结果结构体用GetTickCount()的差值算出 RTT按 ms 输出。3.5 代码骨架itracert.h 里缺失的类型定义补全报告正文里main函数引用了itracert.h中的若干类型但头文件内容没有全部给全。要复现这个程序需要自己补上几个结构定义。按报告的用法这几个定义几乎可以照搬#pragma pack(1) typedef struct _IP_HEADER { UCHAR hdr_len : 4; // IP 头长度单位 4 字节 UCHAR version : 4; // 版本号 UCHAR tos; // 服务类型 USHORT total_len; // 总长度 USHORT id; // 标识 USHORT frag; // 标志与片偏移 UCHAR ttl; // 生存时间 UCHAR protocol; // 上层协议 USHORT checksum; // 首部校验和 ULONG sourceIP; // 源 IP ULONG destIP; // 目的 IP } IP_HEADER; typedef struct _ICMP_HEADER { BYTE type; // 类型8回显请求0回显应答11超时 BYTE code; // 代码 USHORT cksum; // ICMP 校验和 USHORT id; // 标识符 USHORT seq; // 序列号 } ICMP_HEADER; typedef struct _DECODE_RESULT { USHORT usSeqNo; // 期待收到的序列号 DWORD dwRoundTripTime; // 往返时间 in_addr dwIPaddr; // 返回源地址 } DECODE_RESULT;#pragma pack(1)特别重要它强制结构体按 1 字节对齐避免编译器在USHORT前插入填充字节导致头部长度算错。IP 头用位域写hdr_len和version是为了让你能像报告代码那样直接读pIpHdr-hdr_len如果不想用位域也可以用#define加位移提取但对课程设计来说位域更直观。常量方面需要补DEF_MAX_HOP 30、DEF_ICMP_TIMEOUT 3000、DEF_ICMP_DATA_SIZE 32、MAX_ICMP_PACKET_SIZE 1024这是 Windows tracert 的常用参数。4. 编译、运行与结果验证VC6.0 下的完整落地过程4.1 工程配置头文件顺序与 ws2_32.lib 链接VC6.0 搭项目有两个容易卡住的配置点。第一winsock2.h必须放在windows.h之前最好放在所有系统头文件的最前面否则会报一堆Winsock.h 已包含的重定义错误因为旧版的winsock.h和winsock2.h不能共存。这份报告只包含了iostream.h、iomanip.h、winsock2.h、ws2tcpip.h没有显式包含windows.h这样反而更安全。第二原始套接字用到的是 WinSock2 的扩展函数WSASocket、WSAStartup需要在链接参数里加入ws2_32.lib。VC6 的操作路径是Project 菜单 → Settings → Link 标签页 → Object/library modules 末尾加上ws2_32.lib确认无误后编译。漏掉这一步的报错通常是LNK2001: unresolved external symbol __WSAStartup8看到这个错不要怀疑代码直接去链接设置里补库。编译通过后用管理员身份打开命令行在Debug目录下执行itracert.exe 192.168.1.1 itracert.exe www.baidu.com注意 Windows 7 及以上系统创建原始套接字必须要管理员权限。普通 cmd 运行会直接报错误码 10013WSAEACCES这一点血泪经验很多操作时直接在「运行」里以管理员方式启动命令提示符即可。4.2 三种测试场景的预期输出对照测试目标选三个典型场景能在十几分钟内验证程序的正确性。第一个是网关地址比如本机默认网关192.168.1.1正常输出第一跳就是网关自己的 IP而且 RTT 通常在 1ms 左右或显示1 ms因为走的是局域网内部不经过多少处理逻辑第二个是公网目标比如www.baidu.com输出会出现多个条目对应从本地到电信/联通骨干的路径第三个是故意探测一个不存在的内网 IP比如192.168.1.200预期能看到第一跳路由回超时后后面连续输出* Request timed out直到 30 跳上限。输出格式上报告做了对齐处理跳数用setw(3)占三列RTT 用setw(6)占六列超时打印*。1 ms的处理是特意保留的——Windows 的 tracert 同样会把小于 1ms 的时延显示为1 ms这是为了避免用户看到 0ms 误以为计时失效。如果某个中间路由器不回 ICMP 超时报文某些网络设备配置了抑制 ICMP 生成的策略对应跳数会显示* Request timed out但程序会继续往下探测不阻塞整条链路。4.3 和系统 tracert 逐跳对比验证复现完成后把自研程序和系统自带的tracert命令放在一起对比是最好的正确性验证。右键管理员运行两次命令一次是系统tracert -d -h 30 目标-d关闭域名反查避免显示差异干扰判断一次是itracert.exe同一目标C:\ tracert -d -h 30 223.5.5.5 C:\ itracert.exe 223.5.5.5对比两张输出的第一列跳数和第二列 IP 地址。正常情况下每一跳的 IP 应该完全相同只有 RTT 有几十毫秒以内的波动。系统 tracert 每一跳默认发三次包自研程序一跳只发一次RTT 不逐一相等是正常的但 IP 序必须一致。如果出现跳数比系统多或少优先检查自己的超时设置是否太短导致个别跳被跳过以及防火墙是否放行了两者的 ICMP 流量。这一步对比完基本可以确认程序的 ICMP 构造、TTL 设置和解码逻辑都是对的。5. 避坑指南原始套接字课程的六个高发翻车点5.1 一运行就报 10013管理员权限绕不过去现象程序编译链接都通过但一执行就提示Failed to create a raw socket, error code: 10013或者setsockopt返回失败。 原因Windows 从 XP SP2 开始默认限制创建原始套接字SOCK_RAW 只能在管理员权限下创建。普通双击或在普通 cmd 里跑系统直接拒绝。 解决以管理员身份运行右键「以管理员身份运行」打开命令行或者在代码里加一段IsUserAnAdmin检查提示用户提权后再继续。这是这类程序最常见的入门坎不算代码问题。5.2 所有跳数都是 Request timed out防火墙在拦现象程序能跑第一跳就收不到任何回包全链路输出*但系统自带 tracert 也一样超时。 原因Windows 防火墙默认拦截入站 ICMP Echo 报文如果你探测的目标或中间路由器开启了防火墙不回应 ICMP 是正常行为。 解决实验室环境可以临时在防火墙「入站规则」中放行「回显请求 (ICMPv4-In)」实测后记得恢复。真实公网环境部分路由器厂商确实不回应 ICMP 超时报文这种无法强求按「路径黑洞」处理即可。5.3 解码出的 IP 不对载荷偏移算错了现象能收到包但打印出来的 IP 明显不对比如永远是某个内网地址或者 IP 和跳数对应关系混乱。 原因ICMP_TIMEOUT报文里内嵌了原始请求的 IP 头和 ICMP 头需要先跳过外层 IP 头 外层 ICMP 头再跳过内层 IP 头才能读到正确的内层 ICMP 头。漏掉任何一层取到的 id 和 seq 都是错的过滤直接失败。 解决画一张字节偏移图对照着写外层 IP 头长度读hdr_len * 4→ 外层 ICMP 头8 字节→ 内层 IP 头再次读hdr_len * 4→ 内层 ICMP 头。逐层打印偏移值核对一遍确认无误再继续。5.4 校验和算完丢包顺序不对现象程序发出请求后一直超时但用 Wireshark 抓包发现本机发出的 ICMP 包 checksum 是 0或收到了但被目标丢弃。 原因计算校验和之前没有把 ICMP 头的cksum字段清零。校验和的算法要求先置零再计算否则旧值参与累加结果自然错另一个常见原因是字节序没转网络字节序和主机字节序混用。 解决严格按发送顺序来——清零cksum→ 填seq→ 调GenerateChecksum→ 再发送。如果你改了数据长度每次都要重新算不能用上一次的 checksum 复用。5.5 收到一堆不相关的 ICMP 包序列号没过滤现象输出里偶尔混入奇怪的 IP 或跳数错乱不是固定的超时。 原因原始套接字会把网卡收到的所有 ICMP 报文都拷贝一份给程序不匹配请求的包也会进入recvfrom。如果不做过滤直接 break打印的就是别人的回包。 解决DecodeIcmpResponse里必须同时校验id和seqid 等于当前进程 ID、seq 等于当前发送序号才接收。这也是为什么程序要循环recvfrom而不是收到一个就跳出——不匹配就继续读直到匹配或超时。5.6 VC6 里 winsock2.h 和 windows.h 打架现象编译时报一堆redefinition错误定位到winsock2.h和winsock.h的宏冲突。 原因winsock2.h是后来版本老 VC6 的 SDK 同时带有旧版winsock.h。如果代码在包含windows.h之后再包含winsock2.hwindows.h内部的winsock.h会被先加载导致重定义。 解决把#include winsock2.h提到所有系统头文件的最前面必要时定义WIN32_LEAN_AND_MEAN来裁剪windows.h里不相关的部分避开winsock.h的自动引入。链接时别忘了加ws2_32.lib。6. 把课程设计改成可复用诊断工具三次探测取均值与反查主机名报告原始版本每个 TTL 只发一个请求包延时会受瞬时波动影响。我的习惯是随手把它升级成「每跳探测三次取平均」这是从 Linux traceroute 学来的做法。改动量很小在外层while循环里对同一个 TTL 加一个内层 for 循环重复发送三次相同 seq 的 ICMP 包。代码骨架如下for (int probe 0; probe 3; probe) { // 设置 IP_TTL填充 ICMP 头记录发送时间 sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), 0, (sockaddr*)destSockAddr, sizeof(destSockAddr)); // 循环 recvfrom DecodeIcmpResponse直到匹配或超时 // 累计 RTT最后除以 3 输出平均往返时延 } cout \t inet_ntoa(stDecodeResult.dwIPaddr) endl;三次探测的附加价值不只是平均 RTT还能观察某条链路有没有丢包——三次里有一次超时说明这条路径上有随机丢包对判断无线网络或拥塞链路很有意义。第二个顺手改造是给每一跳的 IP 加主机名反查用gethostbyaddr把路由器 IP 翻译成域名很多运维同学习惯直接看节点名判断是哪个城市的出口这个功能对讲清楚「网络结构」很有帮助。注意反查有 DNS 延迟建议只在显示阶段做且失败时静默回退到纯 IP 显示。验证这套改造是否成功仍然拿系统tracert做基准对比同一目标下三次探测计算出的平均 RTT 应当和系统输出同跳时延在一个量级IP 顺序完全一致。如果换了另一门语言重写——比如现在想用 Go 做跨平台版本思路也完全一样TTL 递增、ICMP Echo、超时解码这三块逻辑可以平移到golang.org/x/net/ipv4的SetTTL和icmp包只是省去了手动构建 IP 头这一步。从那以后我每次写网络诊断类程序都会强制走一遍「先抓包看本机发出的报文对不对 → 再对端看回包类型 → 最后对比系统工具的输出」这个流程权限、防火墙、偏移这三类坑基本能在十分钟内定位。尤其是 ICMP 和原始套接字不抓包全靠猜是纯玄学抓到包一切都有定论。希望这份报告和代码能帮你少走几趟弯路。本文还有配套的精品资源点击获取

相关新闻

Vue页面自适应屏幕尺寸:rem动态适配实战方案

Vue页面自适应屏幕尺寸:rem动态适配实战方案

1. 项目概述:为什么“vue开发页面自适应屏幕尺寸”不是一句空话,而是上线前必须死磕的硬门槛在 Vue 项目交付现场,我见过太多次这样的场景:UI 设计稿标注着「适配 iPhone 14 Pro、小米 14、华为 Mate 60、iPad Air」,开…

2026/9/30 5:07:18 阅读更多 →
GOOSE报文解析实战:帧结构、TLV编码与现场避坑记录

GOOSE报文解析实战:帧结构、TLV编码与现场避坑记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 5:07:18 阅读更多 →
AgentScope实战:从零构建生产级记忆型AI Agent

AgentScope实战:从零构建生产级记忆型AI Agent

最近私信和群里被问爆的一个问题:怎么做一个不会“失忆”的AI Agent?很多朋友用各种大模型API搭客服、搭私人助理,第一轮对话效果惊艳,多聊几轮就彻底忘了用户说过什么,你问一句“我上次说的那个预算你还有印象吗”&am…

2026/9/30 5:06:17 阅读更多 →

最新新闻

欧拉法求常微分方程近似解:原理、Python实现与步长稳定性指南

欧拉法求常微分方程近似解:原理、Python实现与步长稳定性指南

欧拉法(Eulers method)求常微分方程近似解,是我见过最容易被轻视、也最容易被误用的数值方法。几乎每个人的第一门数值分析课都会讲它,公式只有一行,代码不到十行,于是很多人写完就丢在一边,转头…

2026/9/30 5:54:40 阅读更多 →
基于双隐含层Elman神经网络的松散回潮出口含水率预测与加水比例反推

基于双隐含层Elman神经网络的松散回潮出口含水率预测与加水比例反推

简介:这份PDF面向卷烟制丝工程技术人员与工业过程控制方向的研究者,聚焦松散回潮出口含水率难以精确控制这一实际难题。资源以Elman神经网络为核心,结合历史生产数据建立加水比例预测模型,将加水比例与环境温湿度作为输入&#xf…

2026/9/30 5:54:40 阅读更多 →
DeepSeek+GPU集群:基层CT影像辅助诊断模型训练实战

DeepSeek+GPU集群:基层CT影像辅助诊断模型训练实战

简介:这份PDF文档面向基层医院影像科医生、医疗AI方向的研究者与工程技术人员,围绕DeepSeek模型与GPU集群部署,讲解如何构建CT影像辅助诊断模型的完整训练流程。内容从医疗影像分析现状与基层医院痛点切入,依次覆盖DeepSeek技术原…

2026/9/30 5:54:40 阅读更多 →
生产级 WebSocket 中继:面向工业边缘的帧级流控与上下文桥接

生产级 WebSocket 中继:面向工业边缘的帧级流控与上下文桥接

1. 项目概述:为什么一个 WebSocket 中继需要“生产级”这个前缀?我第一次在 GitHub 上看到 Orca Cloud Relay 这个项目时,心里其实是有点疑惑的——不就是个 WebSocket 转发器吗?用 Node.js 的ws库写个on(message) → send()就能跑…

2026/9/30 5:54:40 阅读更多 →
GTK入门实战:从零打造Linux原生图形界面

GTK入门实战:从零打造Linux原生图形界面

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 5:54:40 阅读更多 →
Windows 与 Linux 命令对照及终端选型避坑

Windows 与 Linux 命令对照及终端选型避坑

在 Windows 和 Linux 之间来回切换的人,多少都经历过这种尴尬:在 Linux 上肌肉记忆敲出ls,换到 cmd 里一回车,屏幕冷冷回一句"不是内部或外部命令";反过来在 PowerShell 里习惯了Get-ChildItem,登…

2026/9/30 5:53:39 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →