云计算百科
云计算领域专业知识百科平台

Linux:基于TCP Socket的客户端-服务器实现的远程命令行项目

本文将基于一个完整的项目代码,系统讲解如何使用 C++ 实现一个 TCP 客户端与服务器,并重点说明实现过程中所涉及的核心知识点


一、项目整体结构

本项目采用典型的 客户端 – 服务器模型:

  • 客户端:负责连接服务器、发送请求、接收响应

  • 服务器:负责监听连接、处理请求、返回结果

核心模块包括:

InetAddr —— 网络地址封装
TcpServer —— TCP服务器框架
Command —— 业务处理逻辑
Client —— 客户端程序


二、TCP 编程基础知识

在实现之前,需要掌握以下基础知识:


1. Socket 编程模型

TCP 通信基于 socket,基本流程如下:

服务端流程

socket → bind → listen → accept → read/write

客户端流程

socket → connect → read/write


2. 网络字节序

网络传输统一使用 大端字节序,因此需要:

  • htons:主机序 → 网络序(端口)

  • ntohs:网络序 → 主机序

  • inet_pton:字符串 IP → 二进制

  • inet_ntop:二进制 → 字符串 IP


3. sockaddr 结构

TCP 使用:

struct sockaddr_in

但接口统一使用:

struct sockaddr*

因此需要进行类型转换。


三、InetAddr:网络地址封装

为了避免重复操作底层结构,本项目封装了 InetAddr 类。


1. 功能

  • 封装 IP + Port

  • 提供网络序与主机序转换

  • 提供接口给 socket 使用


2. 构造方式

(1)从网络结构构造(服务端 accept)

InetAddr(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. 创建 socket

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

  • SOCK_STREAM 表示 TCP


2. 连接服务器

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::function<std::string(const std::string&, InetAddr&)>;

    👉 表示业务处理函数


    2. 初始化(Init)

    (1)创建 socket

    _listenSockfd = socket(AF_INET, SOCK_STREAM, 0);


    (2)绑定端口

    InetAddr local(_port);
    bind(_listenSockfd, local.NetAddrPtr(), local.NetAddrLen());


    (3)监听

    listen(_listenSockfd, backlog);


    3. 获取连接(accept)

    int sockfd = accept(_listenSockfd, CONV(peer), &len);

    特点:

    • 阻塞等待客户端连接

    • 返回新的通信 socket


    4. 请求处理(Service)

    ssize_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::function<std::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++ 基础

    • 类与对象

    • 构造函数

    • STL(string、function)

    • 智能指针(unique_ptr)


    2. Linux 系统编程

    • socket API

    • 文件描述符

    • read / write

    • close


    3. 网络编程

    • TCP 协议

    • 三次握手(建立连接)

    • 四次挥手(断开连接)

    • 网络字节序


    4. 多线程

    • pthread

    • 线程创建与分离

    • 并发处理模型


    5. 设计思想

    • 封装(InetAddr)

    • 解耦(回调函数)

    • 模块化(TcpServer / Command)

    通过这个项目,可以完整理解 TCP 编程从底层 API 到结构设计的全过程。相比只调用接口,这种方式更有助于深入理解网络通信机制,以及服务器程序的基本构建方式

    这个实现不仅具备基本通信能力,同时具备良好的扩展性,是进一步学习高性能网络编程的重要基础,接下来我们将学习自定义协议,敬请期待啦

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Linux:基于TCP Socket的客户端-服务器实现的远程命令行项目
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!