C语言项目实战】基于 TCP 协议的 Linux 远程终端管理系统(LSD)—— 从零搭建 C/S 架构完整总结
写在前面本文是我在完成「Linux 远程终端管理系统LSD」项目后的完整学习总结。该项目是一个基于 TCP 协议的 C/S 架构系统涵盖了 Linux 网络编程、多线程、链表数据结构、信号处理、文件 IO 等核心知识点。适合有一定 C 语言基础、正在学习 Linux 系统编程的同学参考。一、项目概述1.1 项目简介LSDLinux 远程终端管理系统是一个基于 TCP 协议的 C/S 架构远程终端管理系统实现了多客户端注册登录、远程命令执行、心跳检测、用户间聊天等核心功能。技术栈C 语言 · Linux Socket · pthread 多线程 · 信号处理 · 链表 · 文件 IO开发周期7 天含答辩运行环境Linux / WSL1.2 功能清单功能属性说明TCP 通信搭建必选socket → bind → listen → accept → connect多客户端支持多线程必选pthread_createwhile 循环 accept账户文件文本保存用户数据必选fprintf/fscanf 读写 account.txt注册查重必选遍历用户链表检查用户名是否已存在登录密码验证重复登录检测3次限制必选三重校验机制远程命令ls -l / pwd / ifconfig / ipcs必选popen() 执行并捕获输出链表管理用户链表在线链表互斥锁保护必选双链表 pthread_mutex_t心跳机制客户端每3秒发送必选alarm(3) SIGALRM 信号心跳异常15秒无心跳自动断开必选独立检测线程定期扫描聊天客户端间通过服务器转发必选服务器查找目标 sockfd 转发协议封装struct protocol 统一收发必选结构体打包/拆包配置文件config.ini任选sscanf 解析 keyvalue信号退出CtrlC 优雅退出任选SIGINT 捕获 通知服务器二、系统架构设计2.1 整体架构2.2 项目目录结构2.3 服务器线程模型服务器采用「主线程 accept 子线程处理 检测线程」的三线程模型主线程while(1)循环accept()每收到一个连接就pthread_create开一个子线程子线程client_thread循环read协议包switch-case分发处理心跳检测线程独立线程每 5 秒扫描在线链表超时则断开2.4 客户端线程模型客户端采用「登录前同步 登录后异步」的混合模型登录前主线程自己收发同步通信注册/登录结果直接 read登录后主线程只发不收启动独立的recv_thread负责所有读取异步通信心跳alarm(3)定时触发SIGALRM信号处理函数内发包设计思考为什么登录后要切换为异步因为登录后客户端可能随时收到聊天消息、命令输出、在线用户列表等多种类型的数据如果继续用同步方式主线程在等待用户输入时会阻塞 read导致无法及时接收服务器推送的消息。开一个接收线程就能完美解决这个问题。三、协议包设计核心3.1 协议结构体所有网络通信数据都封装在统一的结构体中3.2 数据包类型定义类型宏值说明TYPE_LOGIN0登录数据包TYPE_REG1注册数据包TYPE_MSG2聊天消息包TYPE_HEART3心跳数据包TYPE_CMD4远程命令包TYPE_ONLINE5查看在线用户TYPE_OK6成功响应TYPE_ERR7错误响应TYPE_QUIT8退出下线包3.3 为什么用结构体而不是字符串面试常考结构体通信 vs 字符串通信的优劣对比项结构体通信字符串通信解析效率直接按字段偏移读取O(1)需要分割/解析O(n)类型安全字段类型明确全是字符串需转换扩展性加字段需改结构体需重新编译双方加分隔符即可跨平台需注意字节序和对齐天然跨平台粘包处理固定大小每次 read 固定字节需自定义分隔符本项目选择结构体通信因为 C/S 双方都是自己写的 C 程序结构体更高效、更直观。四、核心模块详解4.1 TCP 通信搭建服务器端流程踩坑点htons()和ntohs()不能漏端口是 short 类型必须从主机字节序转换为网络字节序大端序否则端口对不上。客户端流程4.2 多线程支持多客户端服务器主循环中每accept到一个新连接就创建一个子线程关键点传给线程函数的参数必须是malloc分配的不能传局部变量地址因为accept循环很快局部变量在下一次循环时会被覆盖子线程可能读到错误数据。在线程函数开头free(info)释放即可。子线程通过switch-case分发协议包4.3 双链表管理 互斥锁两条链表的设计链表节点结构用途用户链表username password保存所有注册用户注册查重 登录验证在线链表username sockfd ip port last_heartbeat保存当前在线用户重复登录检测 聊天转发 心跳检测互斥锁保护两条链表各配一把锁减小锁粒度避免不必要的互斥每次访问链表时加锁、用完即解锁面试考点为什么不只用一把锁用户链表和在线链表是两个独立的资源如果只用一把锁注册操作访问用户链表会阻塞心跳更新访问在线链表造成不必要的等待两把锁各自保护各自的数据互不干扰提高并发性能链表关键操作删除节点在线链表用户下线时调用心跳时间更新收到心跳包时调用4.4 注册功能客户端录入用户名密码 → 打包TYPE_REG发送 → 服务器查重 → 返回结果服务器端处理查重 → 插入链表 → 保存文件4.5 登录功能三重校验登录功能实现了密码验证 重复登录检测 3次限制的三重校验服务器端的双重校验4.6 远程命令执行客户端发送 shell 命令服务器用popen()执行并捕获输出知识扩展popen()vssystem()vsexec()函数能否捕获输出是否阻塞安全性system()不能输出到终端是低命令注入风险popen()能通过管道读是中exec()需配合 dup2替换进程高需 fork本项目选择popen()因为既能执行命令又能捕获输出最简洁。4.7 心跳机制客户端alarm SIGALRM 定时发送关键点信号处理函数内必须再次调用alarm()否则闹钟只响一次。这就实现了「信号 alarm」的周期定时器。服务器独立线程检测超时设计思考删除链表节点时curr被释放了不能用curr curr-next野指针必须用curr prev-next。这是一个容易踩的坑。4.8 聊天功能服务器转发聊天是客户端 → 服务器 → 目标客户端的转发模式为什么需要sockfd → name和name → sockfd两个查找方向sockfd → name服务器收到消息时只知道是哪个 socket 发来的需要反查用户名才能告诉接收者谁发的name → sockfd转发消息时知道目标用户名需要找到对应的 socket 才能发过去4.9 配置文件解析通过fgets逐行读取sscanf解析keyvalue格式4.10 优雅退出信号处理客户端捕获SIGINTCtrlC先通知服务器再退出服务器收到TYPE_QUIT后从在线链表删除该用户五、Makefile 构建项目使用 Makefile 实现模块化编译服务器和客户端分别编译注意必须加-pthread参数否则链接时找不到pthread_create等函数。六、关键技术点总结6.1 知识图谱知识领域涉及的 API / 技术网络编程socket, bind, listen, accept, connect, read, write, close字节序转换htons, ntohs, inet_addr, inet_ntop多线程pthread_create, pthread_detach, pthread_mutex_t信号处理signal, alarm, SIGALRM, SIGINT, SIGPIPE, SIG_IGN文件 IOfopen, fclose, fprintf, fscanf, fgets, popen, pclose链表带头节点的单链表插入/删除/查找/释放配置解析fgets sscanf 解析 keyvalue错误处理perror, errno, ERR_EXIT 宏6.2 踩过的坑与经验坑 1线程参数传递坑 2SIGPIPE 信号导致服务器崩溃当客户端突然断开服务器向已关闭的 socketwrite时会触发SIGPIPE默认行为是终止进程。解决方案坑 3scanf 吃换行符scanf(%d, choice)后输入缓冲区残留\n后续fgets/getchar会读到空行。解决方案坑 4链表删除节点后不能继续用 curr-next坑 5setsockopt 地址复用服务器重启时上次绑定的端口处于TIME_WAIT状态导致bind失败。解决坑 6心跳闹钟只响一次alarm()是一次性的信号处理函数内必须再次调用七、运行效果7.1 编译运行7.2 使用流程7.3 服务器端输出示例八、项目反思与改进方向8.1 当前不足密码明文存储account.txt 中密码是明文实际应用需加密如 MD5/SHA单进程瓶颈多线程模型在大量并发时线程开销大可考虑线程池或 epoll无日志系统目前只 printf 到终端未持久化日志文件命令注入风险popen()直接执行用户输入的命令实际应用需白名单过滤8.2 可扩展方向密码加密存储MD5/SHA256引入 epoll 替代多线程提升并发性能添加日志文件记录连接/命令/断开/心跳超时命令白名单过滤只允许 ls/pwd/ifconfig 等安全命令群聊功能文件传输功能九、总结这个项目虽然不大但麻雀虽小五脏俱全把 Linux C 编程的核心知识点都串了起来知识点在项目中的应用TCP Socket 编程服务器和客户端的通信基础多线程编程服务器并发处理多客户端互斥锁保护全局链表的线程安全信号处理心跳定时器 优雅退出链表数据结构用户管理和在线管理文件 IO账户持久化和配置文件读取结构体协议统一的通信数据格式Makefile模块化编译最大的收获通过在上海职坐标学习编写这个项目真正理解了 C/S 架构的设计思路掌握了 Linux 系统编程的核心 API也踩了不少多线程和信号处理的坑。纸上得来终觉浅绝知此事要躬行。

相关新闻

C++中class与struct的核心区别与工程实践选择指南

C++中class与struct的核心区别与工程实践选择指南

1. 项目概述:为什么C程序员必须厘清类与结构体? 在C的日常开发中,尤其是接手或维护既有代码库时,你大概率会同时遇到 class 和 struct 这两种看似相似却又微妙不同的关键字。很多刚入门的开发者会困惑:它们不都是用…

2026/10/25 15:42:09 阅读更多 →
C++控制台输出格式化:setw、left、right与setfill实战详解

C++控制台输出格式化:setw、left、right与setfill实战详解

1. 从“歪七扭八”到“赏心悦目”:为什么我们需要对齐输出?刚接触C控制台编程时,你是不是也写过这样的代码?打印一个简单的表格,结果数字和文字挤成一团,长短不一,看起来就像被猫抓过的毛线球。…

2026/10/25 7:11:27 阅读更多 →
从零构建QQ机器人:Python+NoneBot2+go-cqhttp完整开发部署指南

从零构建QQ机器人:Python+NoneBot2+go-cqhttp完整开发部署指南

1. 项目概述:从零构建一个能说会道的QQ机器人 最近几年,QQ机器人从极客圈的小众玩具,逐渐变成了社群管理、游戏陪玩、信息查询的得力助手。你可能在群里见过自动回复关键词的“龙王”,或者能陪你玩文字游戏的“修仙”机器人。作为…

2026/10/25 6:40:55 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/25 11:19:54 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/24 17:47:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/24 18:34:36 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/25 10:02:42 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/25 3:12:30 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/24 21:09:59 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/25 10:02:43 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/25 7:47:32 阅读更多 →