Linux:基于TCP Socket的客户端-服务器实现的远程命令行项目
本文将基于一个完整的项目代码系统讲解如何使用 C 实现一个 TCP 客户端与服务器并重点说明实现过程中所涉及的核心知识点一、项目整体结构本项目采用典型的客户端 - 服务器模型客户端负责连接服务器、发送请求、接收响应服务器负责监听连接、处理请求、返回结果核心模块包括InetAddr —— 网络地址封装 TcpServer —— TCP服务器框架 Command —— 业务处理逻辑 Client —— 客户端程序二、TCP 编程基础知识在实现之前需要掌握以下基础知识1. Socket 编程模型TCP 通信基于 socket基本流程如下服务端流程socket → bind → listen → accept → read/write客户端流程socket → connect → read/write2. 网络字节序网络传输统一使用大端字节序因此需要htons主机序 → 网络序端口ntohs网络序 → 主机序inet_pton字符串 IP → 二进制inet_ntop二进制 → 字符串 IP3. sockaddr 结构TCP 使用struct sockaddr_in但接口统一使用struct sockaddr*因此需要进行类型转换。三、InetAddr网络地址封装为了避免重复操作底层结构本项目封装了InetAddr类。1. 功能封装 IP Port提供网络序与主机序转换提供接口给 socket 使用2. 构造方式1从网络结构构造服务端 acceptInetAddr(const sockaddr_in addr)作用提取 IP转换端口为主机序2客户端构造InetAddr(const std::string ip, uint16_t port)作用构造用于 connect 的地址结构3服务端构造InetAddr(uint16_t port)特点IP 设置为INADDR_ANY监听所有网卡3. 核心接口const struct sockaddr* NetAddrPtr(); const size_t NetAddrLen(); 用于 socket API 调用四、客户端实现客户端逻辑较为简单核心代码如下1. 创建 socketint sockfd socket(AF_INET, SOCK_STREAM, 0);SOCK_STREAM表示 TCP2. 连接服务器connect(sockfd, cilent.NetAddrPtr(), cilent.NetAddrLen());3. 数据通信write(sockfd, line.c_str(), line.size()); read(sockfd, buffer, sizeof(buffer));流程从标准输入读取数据发送给服务器接收服务器返回结果输出到终端4. 关闭连接close(sockfd);五、TcpServer服务器实现服务器是整个项目的核心。1. 成员变量uint16_t _port; int _listenSockfd; bool _isrunning; func_t _func;其中using func_t std::functionstd::string(const std::string, InetAddr); 表示业务处理函数2. 初始化Init1创建 socket_listenSockfd socket(AF_INET, SOCK_STREAM, 0);2绑定端口InetAddr local(_port); bind(_listenSockfd, local.NetAddrPtr(), local.NetAddrLen());3监听listen(_listenSockfd, backlog);3. 获取连接acceptint sockfd accept(_listenSockfd, CONV(peer), len);特点阻塞等待客户端连接返回新的通信 socket4. 请求处理Servicessize_t n read(sockfd, buffer, sizeof(buffer));处理逻辑读取客户端数据调用业务函数_func将结果返回给客户端std::string result _func(buffer, cilent); write(sockfd, result.c_str(), result.size());5. 并发处理多线程为了支持多个客户端同时访问使用 pthread线程数据封装class ThreadData { TcpServer* _tsvr; int _sockfd; InetAddr _addr; };线程入口函数static void* Routine(void* args)流程分离线程pthread_detach执行Service释放资源创建线程pthread_create(tid, nullptr, Routine, td); 每个客户端一个线程六、业务解耦回调机制服务器不直接处理业务逻辑而是通过回调函数std::functionstd::string(const std::string, InetAddr)在 main 中绑定std::bind(Command::Execute, cmd, std::placeholders::_1, std::placeholders::_2)优点服务器只负责通信业务逻辑独立可扩展性强七、Command 模块业务层该模块负责处理客户端请求std::string Execute(const std::string req, InetAddr client);功能可以是字符串处理命令执行数据查询八、程序运行流程总结服务端启动 → 初始化socket → 监听端口 → accept连接 → 创建线程 → 处理请求客户端启动 → 创建socket → connect服务器 → 输入数据 → 接收响应九、涉及的核心知识总结实现本项目需要掌握以下知识1. C 基础类与对象构造函数STLstring、function智能指针unique_ptr2. Linux 系统编程socket API文件描述符read / writeclose3. 网络编程TCP 协议三次握手建立连接四次挥手断开连接网络字节序4. 多线程pthread线程创建与分离并发处理模型5. 设计思想封装InetAddr解耦回调函数模块化TcpServer / Command通过这个项目可以完整理解 TCP 编程从底层 API 到结构设计的全过程。相比只调用接口这种方式更有助于深入理解网络通信机制以及服务器程序的基本构建方式这个实现不仅具备基本通信能力同时具备良好的扩展性是进一步学习高性能网络编程的重要基础接下来我们将学习自定义协议敬请期待啦