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/7/29 6:36:47 阅读更多 →
C++控制台输出格式化:setw、left、right与setfill实战详解

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

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

2026/7/29 6:35:47 阅读更多 →
从零构建QQ机器人:Python+NoneBot2+go-cqhttp完整开发部署指南

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

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

2026/7/29 6:35:47 阅读更多 →

最新新闻

行空板M10嵌入式语音合成实战:集成讯飞离线与百度云端双引擎

行空板M10嵌入式语音合成实战:集成讯飞离线与百度云端双引擎

1. 项目缘起:为什么要在行空板上折腾语音引擎?最近在做一个智能交互小装置,核心需求是让设备能“听懂人话”并“开口说话”。手头正好有一块行空板M10,它集成了高性能的处理器和丰富的接口,跑个Linux系统,做…

2026/7/29 6:49:53 阅读更多 →
Android崩溃分析实战:用Python脚本打通Logcat与Firebase Crashlytics

Android崩溃分析实战:用Python脚本打通Logcat与Firebase Crashlytics

1. 项目概述:为什么我们需要一个专门的Logcat插件来分析Firebase崩溃? 如果你是一名Android开发者,尤其是在处理线上应用崩溃问题时,Firebase Crashlytics(现在已整合到Firebase Crash Reporting中)几乎是…

2026/7/29 6:49:53 阅读更多 →
多传感器融合算法:从UKF到AUKF的工程实践

多传感器融合算法:从UKF到AUKF的工程实践

1. 多传感器融合与状态估计的核心挑战在自动驾驶、机器人导航和工业控制等领域,多传感器数据融合一直是提升系统鲁棒性的关键技术。我十年前第一次接触无人机飞控项目时,就深刻体会到单一传感器的局限性——GPS信号丢失时姿态估计完全失效,这…

2026/7/29 6:49:53 阅读更多 →
Flut Renamer:免费高效的跨平台批量文件重命名终极指南

Flut Renamer:免费高效的跨平台批量文件重命名终极指南

Flut Renamer:免费高效的跨平台批量文件重命名终极指南 【免费下载链接】renamer Flut Renamer - A bulk file renamer written in flutter (dart). Available on Linux, Windows, Android, iOS and macOS. 项目地址: https://gitcode.com/gh_mirrors/ren/renamer…

2026/7/29 6:49:53 阅读更多 →
王者荣耀战绩查询API实战:搜索玩家、查看角色与历史战报

王者荣耀战绩查询API实战:搜索玩家、查看角色与历史战报

适用场景 当开发者需要将王者荣耀战绩数据集成到自己的应用中时,例如: 战队数据看板:自动拉取队员近期的排位赛、巅峰赛表现,生成 KDA 统计报表直播辅助工具:主播输入玩家昵称,实时展示当前段位和历史战报个…

2026/7/29 6:49:53 阅读更多 →
从SSRF到Pickle反序列化:Web渗透中的链式漏洞利用实战

从SSRF到Pickle反序列化:Web渗透中的链式漏洞利用实战

1. 项目概述:一次从SSRF到Pickle反序列化的完整攻防推演最近复盘了去年长城杯的一道Web赛题,感觉它把SSRF(服务端请求伪造)和Python Pickle反序列化这两个经典漏洞串联得相当巧妙,实战价值很高。这道题不是那种简单的“…

2026/7/29 6:48:52 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻