• 04.基于C++实现多线程TCP服务器与客户端通信

04.基于C++实现多线程TCP服务器与客户端通信

2025-04-26 06:52:10 0 阅读

基于C++实现多线程TCP服务器与客户端通信

目录

  • 一、项目背景与目标
  • 二、从零开始理解网络通信
  • 三、相关技术背景知识
    • 1. 守护进程(Daemon Process)
    • 2. 线程池(Thread Pool)
    • 3. RAII设计模式
  • 四、项目整体结构与逻辑
  • 五、核心模块详细分析
    • 1. TCP服务器模块
    • 2. 线程池模块
    • 3. 任务处理模块
    • 4. 日志模块
    • 5. 守护进程模块
    • 6. 锁管理模块
  • 六、从实践到理论:关键设计模式与技术
  • 七、进阶主题与扩展思考
  • 八、总结与展望

一、项目背景与目标

在网络编程中,TCP协议因其可靠性和稳定性被广泛应用于各类网络服务。本项目使用C++语言,基于Linux平台实现了一个完整的TCP服务器与客户端通信程序,服务器端采用了线程池技术实现高效并发处理,支持守护进程运行,并实现了完整的日志系统。

本项目的目标是:

  • 掌握TCP协议的基本编程方法
  • 掌握线程池的设计与实现
  • 学习守护进程的创建与管理
  • 掌握日志系统的设计与实现
  • 理解RAII设计模式在资源管理中的应用

二、从零开始理解网络通信

网络通信的本质

想象一下,当你给朋友发送一条短信时,这条信息是如何从你的手机传递到朋友的手机的?这个过程涉及:

  1. 你的手机将信息编码
  2. 通过无线信号发送到基站
  3. 基站将信息路由到目标手机
  4. 目标手机接收并解码信息

计算机网络通信也遵循类似的原理,只是更加复杂和规范化。TCP/IP协议就像是计算机之间沟通的"语言规则",确保信息能够正确传递。

套接字(Socket):网络通信的基础

套接字可以理解为网络通信的"插座",就像家里的电源插座连接电器一样,套接字连接网络中的应用程序。

应用程序 <---> 套接字 <---> 网络 <---> 套接字 <---> 应用程序

在我们的项目中:

// 创建套接字
_sock = socket(AF_INET, SOCK_STREAM, 0);

这行代码就像是安装了一个"网络插座",其中:

  • AF_INET表示使用IPv4地址
  • SOCK_STREAM表示使用TCP协议
  • 0表示使用默认协议

三、相关技术背景知识

1. 守护进程(Daemon Process):服务器的"隐形模式"

想象一下,如果你的手机应用必须保持前台运行才能接收消息,那将是多么不便!守护进程就像是手机的"后台应用",即使你关闭了终端窗口,它仍然在默默工作。

守护进程的创建过程可以类比为一个员工的"独立":

  1. 创建子进程并退出父进程:就像员工从公司分离出来成立自己的工作室
  2. 创建新会话:员工不再接受原公司的直接管理
  3. 重定向输入输出:员工建立了自己的沟通渠道
  4. 更改工作目录:员工搬到了新的办公地点
// 创建守护进程的关键步骤
if (fork() > 0) exit(0);  // 父进程退出
pid_t n = setsid();       // 创建新会话

2. 线程池(Thread Pool):高效的"工作团队"

想象一家餐厅:

  • 如果每来一位客人就雇佣一名新服务员,成本会非常高
  • 如果只有一名服务员,客人可能需要长时间等待
  • 最佳方案是维持一个固定数量的服务员团队,随时准备服务新客人

线程池就是这样的"服务员团队":

  • 预先创建多个线程,等待任务分配
  • 当新任务到来时,从线程池中分配一个空闲线程处理
  • 任务完成后,线程返回池中等待下一个任务
// 线程池的核心:等待并处理任务
while (true) {
    T t;
    {
        LockGuard lockguard(td->threadpool->mutex());
        while (td->threadpool->isQueueEmpty()) {
            td->threadpool->threadWait();  // 等待新任务
        }
        t = td->threadpool->pop();  // 获取任务
    }
    t();  // 执行任务
}

3. RAII(Resource Acquisition Is Initialization):智能资源管理

RAII就像是一个自动化的"资源管家"。想象你去图书馆:

  • 进门时,你借了一本书(获取资源)
  • 离开时,你必须归还这本书(释放资源)
  • 如果你忘记归还,图书馆会有麻烦

RAII确保:

  • 当你"进门"(创建对象)时,自动借书(获取资源)
  • 当你"离开"(对象销毁)时,自动还书(释放资源)
  • 即使发生意外(如异常),也能确保书被归还
// RAII的典型应用:自动管理锁
{
    LockGuard lockguard(&_mutex);  // 构造时自动加锁
    _task_queue.push(in);
    pthread_cond_signal(&_cond);
}  // 离开作用域时自动解锁

四、项目整体结构与逻辑

项目模块关系图

                  +-------------+
                  | tcpServer.cc|
                  +------+------+
                         |
                         v
+----------+      +------+-------+      +-----------+
| daemon.hpp|<-----| tcpServer.hpp|----->|  Task.hpp |
+----------+      +------+-------+      +-----+-----+
                         |                    |
                         v                    v
                  +------+-------+     +------+------+
                  |ThreadPool.hpp|<----|serviceIO()  |
                  +------+-------+     +-------------+
                         |
                         v
                  +------+-------+
                  |  Thread.hpp  |
                  +------+-------+
                         |
                         v
                  +------+-------+
                  | LockGuard.hpp|
                  +-------------+

项目整体运行流程

想象一个餐厅的运作流程:

  1. 餐厅开业(服务器启动):

    • 准备场地(创建套接字)
    • 挂出营业牌(绑定端口)
    • 组建服务团队(初始化线程池)
    • 开始迎接客人(监听连接)
  2. 客人到来(客户端连接):

    • 服务员引导入座(accept接受连接)
    • 分配一名服务员(从线程池分配线程)
    • 开始点餐服务(处理客户端请求)
  3. 服务过程(数据交换):

    • 客人点餐(客户端发送数据)
    • 服务员记录并确认(服务器处理并回应)
    • 上菜(服务器返回结果)
  4. 就餐结束(连接关闭):

    • 客人离开(客户端断开连接)
    • 服务员清理桌面(关闭socket)
    • 准备服务下一位客人(线程返回池中)

五、核心模块详细分析

1. TCP服务器模块 (tcpServer.hpptcpServer.cc)

设计思路:建立通信的"桥梁"

TCP服务器就像是一个电话总机,负责接听来电并将其转接给合适的接线员。其主要职责是:

  • 创建通信渠道(套接字)
  • 公布联系方式(绑定地址和端口)
  • 等待来电(监听连接)
  • 接听并转接(接受连接并提交给线程池)
关键代码解析
void initServer() {
    // 1. 创建通信渠道
    _listensock = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2. 绑定地址和端口(公布联系方式)
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(_port);
    local.sin_addr.s_addr = INADDR_ANY;
    bind(_listensock, (struct sockaddr *)&local, sizeof(local));
    
    // 3. 开始监听(等待来电)
    listen(_listensock, gbacklog);
}

void start() {
    // 4. 准备接线员团队(初始化线程池)
    ThreadPool<Task>::getInstance()->run();
    
    for (;;) {
        // 5. 接听来电
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
        
        // 6. 转接给接线员(提交任务到线程池)
        ThreadPool<Task>::getInstance()->push(Task(sock, serviceIO));
    }
}
实现要点与技巧
  • 错误处理的重要性:网络编程中,各种意外情况都可能发生(端口被占用、连接突然断开等)。良好的错误处理能让程序更加健壮。

  • 为什么使用INADDR_ANY:使用INADDR_ANY(值为0.0.0.0)允许服务器监听所有网络接口,无论客户端从哪个网卡连接都能接受。

  • backlog参数的意义listen(_listensock, gbacklog)中的gbacklog表示等待连接队列的最大长度。当连接请求过多时,超过这个值的连接会被拒绝。

2. 线程池模块 (ThreadPool.hppThread.hpp)

设计思路:高效的"工作团队"

线程池就像一个高效的工作团队:

  • 预先组建团队(创建线程)
  • 统一分配任务(任务队列)
  • 团队成员互相协作(线程同步)
  • 避免重复招聘(线程复用)
关键代码解析
// 线程的工作循环
static void *handlerTask(void *args) {
    ThreadData<T> *td = (ThreadData<T> *)args;
    while (true) {
        T t;
        {
            // 1. 等待任务分配
            LockGuard lockguard(td->threadpool->mutex());
            while (td->threadpool->isQueueEmpty()) {
                td->threadpool->threadWait();  // 没有任务时等待
            }
            // 2. 领取任务
            t = td->threadpool->pop();
        }
        // 3. 执行任务
        t();
    }
    return nullptr;
}

// 添加新任务
void push(const T &in) {
    // 1. 锁定任务队列
    LockGuard lockguard(&_mutex);
    // 2. 添加任务
    _task_queue.push(in);
    // 3. 通知等待的线程
    pthread_cond_signal(&_cond);
}
实现要点与技巧
  • 为什么使用条件变量:条件变量允许线程在特定条件满足前进入睡眠状态,避免了忙等待(不断检查条件)带来的CPU资源浪费。

  • 单例模式的优势:整个程序只需要一个线程池实例,单例模式确保了资源的统一管理,避免了重复创建带来的开销。

  • 双重检查锁定:在getInstance()方法中使用双重检查锁定,既保证了线程安全,又避免了每次获取实例都加锁带来的性能损失。

  • 模板设计的灵活性:使用模板设计线程池,使其能够处理不同类型的任务,提高了代码的复用性。

3. 任务处理模块 (Task.hpp)

设计思路:统一的任务接口

任务处理模块就像是一个标准化的"工作指南":

  • 定义了工作内容(处理客户端连接)
  • 提供了统一的执行方式(operator())
  • 封装了具体实现细节(回调函数)
关键代码解析
// 具体的任务处理函数
void serviceIO(int sock) {
    char buffer[1024];
    while (true) {
        // 1. 接收客户端数据
        ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
        if (n > 0) {
            // 2. 处理数据
            buffer[n] = 0;
            std::cout << "recv message: " << buffer << std::endl;
            
            // 3. 准备响应
            std::string outbuffer = buffer;
            outbuffer += " server[echo]";
            
            // 4. 发送响应
            write(sock, outbuffer.c_str(), outbuffer.size());
        }
        else if (n == 0) {
            // 5. 客户端断开连接
            logMessage(NORMAL, "client quit, me too!");
            break;
        }
    }
    // 6. 关闭连接
    close(sock);
}

// 任务封装类
class Task {
    using func_t = std::function<void(int)>;
    
public:
    Task(int sock, func_t func)
        : _sock(sock), _callback(func) {}
    
    // 统一的任务执行接口
    void operator()() {
        _callback(_sock);
    }
    
private:
    int _sock;
    func_t _callback;
};
实现要点与技巧
  • 为什么使用std::functionstd::function提供了一种类型安全的函数封装,可以存储、复制和调用任何可调用目标(函数、lambda表达式、函数对象等)。

  • 为什么重载operator():重载operator()使Task对象可以像函数一样被调用,符合线程池对任务的要求,同时提供了更清晰的接口。

  • read/write vs recv/send:本项目使用read/write而非recv/send,因为前者更符合Unix “一切皆文件” 的哲学,可以统一处理文件、管道、套接字等I/O操作。

  • 为什么接收用char[]而发送用string

    • 接收数据时使用固定大小的char[]缓冲区,可以直接与系统调用配合,避免动态内存分配
    • 发送数据时使用string,便于字符串操作(如拼接)
    • 最后通过c_str()转换回C风格字符串进行发送

4. 日志模块 (log.hpp)

设计思路:系统的"黑匣子"

日志系统就像飞机的黑匣子,记录系统运行的各种状态和事件:

  • 不同级别的日志(从调试信息到致命错误)
  • 详细的时间和上下文信息
  • 持久化存储,便于后期分析
关键代码解析
void logMessage(int level, const char *format, ...) {
    // 1. 构建日志前缀
    char logprefix[NUM];
    snprintf(logprefix, sizeof(logprefix), "[%s][%ld][pid: %d]",
        to_levelstr(level), (long int)time(nullptr), getpid());
    
    // 2. 处理可变参数
    char logcontent[NUM];
    va_list arg;
    va_start(arg, format);
    vsnprintf(logcontent, sizeof(logcontent), format, arg);
    va_end(arg);
    
    // 3. 选择日志文件
    FILE *log = fopen(LOG_NORMAL, "a");
    FILE *err = fopen(LOG_ERR, "a");
    
    if(log != nullptr && err != nullptr) {
        FILE *curr = nullptr;
        if(level <= WARNING) curr = log;
        else curr = err;
            
        // 4. 写入日志
        if(curr) fprintf(curr, "%s%s
", logprefix, logcontent);
        
        fclose(log);
        fclose(err);
    }
}
实现要点与技巧
  • 可变参数的处理:使用va_listva_startva_endvsnprintf处理可变参数,实现了类似printf的灵活接口。

  • 日志分级的意义

    • DEBUG:详细的调试信息,帮助开发者理解程序流程
    • NORMAL:正常操作信息,记录系统的正常活动
    • WARNING:警告信息,表示可能的问题但不影响主要功能
    • ERROR:错误信息,表示功能受到影响但系统仍能运行
    • FATAL:致命错误,表示系统无法继续运行
  • 为什么分文件存储:将普通日志和错误日志分开存储,便于快速定位问题,同时避免重要的错误信息被大量普通日志淹没。

  • 时间戳和进程ID:记录时间戳和进程ID,便于在多进程环境下追踪问题,确定事件发生的顺序。

5. 守护进程模块 (daemon.hpp)

设计思路:服务器的"隐形模式"

守护进程就像是系统的"隐形服务员":

  • 脱离用户控制(不依赖终端)
  • 在后台默默工作(不显示输出)
  • 长期稳定运行(不受用户登录状态影响)
关键代码解析
void daemonSelf(const char *currPath = nullptr) {
    // 1. 忽略管道破裂信号
    signal(SIGPIPE, SIG_IGN);
    
    // 2. 创建子进程,父进程退出
    if (fork() > 0)
        exit(0);
        
    // 3. 创建新会话,脱离控制终端
    pid_t n = setsid();
    assert(n != -1);
    
    // 4. 重定向标准输入输出
    int fd = open(DEV, O_RDWR);
    if(fd >= 0) {
        dup2(fd, 0);  // 标准输入
        dup2(fd, 1);  // 标准输出
        dup2(fd, 2);  // 标准错误
        close(fd);
    }
    
    // 5. 更改工作目录
    if(currPath) chdir(currPath);
}
实现要点与技巧
  • 为什么忽略SIGPIPE信号:当写入一个已关闭的管道或套接字时,系统会发送SIGPIPE信号,默认处理是终止进程。忽略此信号可以防止服务器因客户端异常断开而崩溃。

  • 为什么使用fork():使用fork()创建子进程,然后父进程退出,使子进程成为孤儿进程,被init进程收养,从而脱离原来的控制终端。

  • setsid()的作用setsid()创建一个新的会话,使进程成为会话首进程,没有控制终端,不会接收终端相关的信号。

  • 为什么重定向到/dev/null:重定向标准输入输出到/dev/null,确保进程不会因为读写终端而阻塞,同时避免输出信息干扰系统运行。

6. 锁管理模块 (LockGuard.hpp)

设计思路:自动化的"资源管家"

锁管理模块就像是一个自动化的门禁系统:

  • 进入区域时自动上锁(构造函数中加锁)
  • 离开区域时自动解锁(析构函数中解锁)
  • 确保资源安全,避免冲突(线程安全)
关键代码解析
class Mutex {
public:
    Mutex(pthread_mutex_t *lock_p = nullptr): lock_p_(lock_p) {}
    
    void lock() {
        if(lock_p_) pthread_mutex_lock(lock_p_);
    }
    
    void unlock() {
        if(lock_p_) pthread_mutex_unlock(lock_p_);
    }
    
private:
    pthread_mutex_t *lock_p_;
};

class LockGuard {
public:
    LockGuard(pthread_mutex_t *mutex): mutex_(mutex) {
        mutex_.lock();  // 构造时自动加锁
    }
    
    ~LockGuard() {
        mutex_.unlock();  // 析构时自动解锁
    }
    
private:
    Mutex mutex_;
};
实现要点与技巧
  • RAII的优势:使用RAII模式管理锁资源,无需手动解锁,即使发生异常也能确保锁被释放,避免死锁。

  • 分离Mutex和LockGuard:将Mutex和LockGuard分开实现,提高了代码的复用性和灵活性。Mutex封装了底层锁操作,LockGuard提供了RAII风格的接口。

  • 空指针检查:在lock()和unlock()方法中检查指针是否为空,提高了代码的健壮性,避免空指针异常。

  • 使用示例

    {
        LockGuard guard(&mutex);  // 进入作用域,自动加锁
        // 临界区代码...
    }  // 离开作用域,自动解锁
    

六、从实践到理论:关键设计模式与技术

1. 单例模式(Singleton Pattern)

定义:确保一个类只有一个实例,并提供一个全局访问点。

应用:线程池使用单例模式,确保整个程序只有一个线程池实例。

优势

  • 节约系统资源,避免重复创建
  • 提供全局访问点,方便使用
  • 确保所有组件使用同一个实例

实现

static ThreadPool<T> *getInstance() {
    if (nullptr == tp) {
        _singlock.lock();
        if (nullptr == tp) {
            tp = new ThreadPool<T>();
        }
        _singlock.unlock();
    }
    return tp;
}

2. 观察者模式(Observer Pattern)的变体

定义:定义对象间的一种一对多依赖关系,使得当一个对象状态改变时,所有依赖于它的对象都会得到通知。

应用:线程池中的条件变量机制实际上是观察者模式的一种变体。

优势

  • 解耦了任务生产者和消费者
  • 支持一对多的通知机制
  • 提高了系统的灵活性

实现

// 生产者(通知者)
void push(const T &in) {
    LockGuard lockguard(&_mutex);
    _task_queue.push(in);
    pthread_cond_signal(&_cond);  // 通知等待的线程
}

// 消费者(观察者)
while (td->threadpool->isQueueEmpty()) {
    td->threadpool->threadWait();  // 等待通知
}

3. 工厂方法模式(Factory Method Pattern)

定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。

应用:Task类使用了工厂方法模式的思想,通过回调函数创建不同的任务处理逻辑。

优势

  • 将对象的创建与使用分离
  • 支持扩展,可以轻松添加新的任务类型
  • 提高了代码的可维护性

实现

Task(int sock, func_t func)
    : _sock(sock), _callback(func) {}

void operator()() {
    _callback(_sock);  // 调用工厂方法创建的处理逻辑
}

七、进阶主题与扩展思考

1. 性能优化

连接池:除了线程池,还可以实现连接池,预先建立和维护一组数据库连接,避免频繁创建和销毁连接的开销。

零拷贝技术:使用sendfile()等系统调用,减少数据在内核空间和用户空间之间的拷贝,提高文件传输效率。

事件驱动模型:使用epollkqueue等I/O多路复用技术,实现高效的事件驱动模型,支持更多并发连接。

2. 安全性考虑

输入验证:对客户端输入进行严格验证,防止缓冲区溢出、SQL注入等攻击。

加密通信:实现SSL/TLS加密,保护数据传输安全。

资源限制:对连接数、请求频率等进行限制,防止DoS攻击。

3. 可扩展性设计

插件系统:设计插件接口,支持动态加载功能模块。

配置中心:实现集中式配置管理,支持动态配置更新。

服务发现:集成服务发现机制,支持分布式部署。

八、总结与展望

本项目实现了一个完整的TCP服务器与客户端通信系统,涵盖了网络编程、多线程编程、线程池、守护进程、日志系统等多个核心知识点。通过模块化设计和面向对象编程,我们构建了一个结构清晰、功能完善的网络服务框架。

从这个项目出发,你可以进一步探索:

  • 实现HTTP/WebSocket等应用层协议
  • 集成数据库访问功能
  • 实现负载均衡和高可用设计
  • 探索异步I/O和协程技术

网络编程是现代软件开发的基础技能,希望这个项目能够帮助你打开网络编程的大门,为你的技术成长提供坚实的基础。

本文地址:https://www.vps345.com/1575.html

搜索文章

Tags

PV计算 带宽计算 流量带宽 服务器带宽 上行带宽 上行速率 什么是上行带宽? CC攻击 攻击怎么办 流量攻击 DDOS攻击 服务器被攻击怎么办 源IP 服务器 linux 运维 游戏 云计算 javascript 前端 chrome edge python MCP llama 算法 opencv 自然语言处理 神经网络 语言模型 ssh deepseek Ollama 模型联网 API CherryStudio 进程 操作系统 进程控制 Ubuntu harmonyos 华为 开发语言 typescript 计算机网络 ubuntu 数据库 centos oracle 关系型 安全 分布式 react.js 前端面试题 node.js 持续部署 Dell R750XS 科技 ai java 人工智能 个人开发 udp unity 网络 网络协议 rust http macos adb fastapi mcp mcp-proxy mcp-inspector fastapi-mcp agent sse pycharm ide pytorch numpy nginx 监控 自动化运维 阿里云 网络安全 django flask web3.py 笔记 C 环境变量 进程地址空间 github 创意 社区 flutter RTSP xop RTP RTSPServer 推流 视频 tcp/ip golang AI 爬虫 数据集 面试 性能优化 jdk intellij-idea 架构 oceanbase rc.local 开机自启 systemd 麒麟 ecm bpm 深度学习 机器学习 chatgpt 大模型 llama3 Chatglm 开源大模型 php android c# c++ 深度优先 图论 并集查找 换根法 树上倍增 ddos ollama llm zotero WebDAV 同步失败 代理模式 ansible playbook YOLO vue.js audio vue音乐播放器 vue播放音频文件 Audio音频播放器自定义样式 播放暂停进度条音量调节快进快退 自定义audio覆盖默认样式 java-ee bash sql KingBase 银河麒麟 kylin v10 麒麟 v10 Docker Compose docker compose docker-compose 目标检测 计算机视觉 conda spring spring boot 后端 tomcat postman mock mock server 模拟服务器 mock服务器 Postman内置变量 Postman随机数据 ESP32 LDAP websocket 自动化 maven intellij idea 腾讯云 nuxt3 vue3 docker 实时音视频 filezilla 无法连接服务器 连接被服务器拒绝 vsftpd 331/530 dubbo .netcore 运维开发 容器 .net ssl 统信 国产操作系统 虚拟机安装 openEuler gitlab 低代码 多线程服务器 Linux网络编程 android studio pillow live555 rtsp rtp json html5 firefox c语言 web安全 Kali Linux 黑客 渗透测试 信息收集 kubernetes 学习方法 经验分享 程序人生 Qwen2.5-coder 离线部署 vim vscode 代码调试 ipdb springsecurity6 oauth2 授权服务器 token sas DeepSeek-R1 API接口 Flask FastAPI Waitress Gunicorn uWSGI Uvicorn prometheus Hyper-V WinRM TrustedHosts kvm 无桌面 命令行 串口服务器 apache matlab YOLOv8 NPU Atlas800 A300I pro asi_bench mount挂载磁盘 wrong fs type LVM挂载磁盘 Centos7.9 蓝耘科技 元生代平台工作流 ComfyUI windows 搜索引擎 Deepseek 智能路由器 dell服务器 IIS .net core Hosting Bundle .NET Framework vs2022 rabbitmq es jvm html elasticsearch jenkins minio Spring Security microsoft redis 计算机 jupyter kylin Invalid Host allowedHosts vue 远程连接 rdp 实验 远程工作 fpga开发 负载均衡 mysql gitee Wi-Fi WebUI DeepSeek V3 DeepSeek AI大模型 交换机 硬件 设备 GPU PCI-Express minicom 串口调试工具 测试工具 GaN HEMT 氮化镓 单粒子烧毁 辐射损伤 辐照效应 矩阵 线性代数 电商平台 UOS 统信操作系统 yum SysBench 基准测试 qt 交叉编译 嵌入式 C++软件实战问题排查经验分享 0xfeeefeee 0xcdcdcdcd 动态库加载失败 程序启动失败 程序运行权限 标准用户权限与管理员权限 ISO镜像作为本地源 mybatis MacOS录屏软件 AIGC 云电竞 云电脑 todesk svn 学习 嵌入式硬件 职场和发展 MNN Qwen 备份SQL Server数据库 数据库备份 傲梅企业备份网络版 大数据 cursor 音乐服务器 Navidrome 音流 transformer 游戏服务器 Minecraft pip H3C ESXi Dell HPE 联想 浪潮 AI编程 CPU 内存 主板 电源 网卡 医疗APP开发 app开发 uni-app virtualenv arm debian pppoe radius arm开发 系统安全 媒体 微信 远程桌面 gaussdb ffmpeg 音视频 xss 宝塔面板访问不了 宝塔面板网站访问不了 宝塔面板怎么配置网站能访问 宝塔面板配置ip访问 宝塔面板配置域名访问教程 宝塔面板配置教程 kind 开源 华为云 物联网 react next.js 部署 部署next.js QQ 聊天室 spring cloud 单片机 温湿度数据上传到服务器 Arduino HTTP ocr 命令 AI agent 硬件架构 系统架构 思科模拟器 思科 Cisco 云服务 googlecloud eureka https muduo X11 Xming 小程序 其他 银河麒麟服务器操作系统 系统激活 git 弹性计算 虚拟化 KVM 计算虚拟化 弹性裸金属 c 博客 游戏程序 stm32 windwos防火墙 defender防火墙 win防火墙白名单 防火墙白名单效果 防火墙只允许指定应用上网 防火墙允许指定上网其它禁止 社交电子 安全威胁分析 安装教程 GPU环境配置 Ubuntu22 CUDA PyTorch Anaconda安装 vscode 1.86 远程登录 telnet 1024程序员节 重启 排查 系统重启 日志 原因 漏洞 信息与通信 ip k8s 智能手机 NAS Termux Samba Linux SSH 计算机外设 电脑 mac 软件需求 express p2p 云原生 5G 3GPP 卫星通信 hugo WSL2 Netty 即时通信 NIO SWAT 配置文件 服务管理 网络共享 监控k8s集群 集群内prometheus HTTP 服务器控制 ESP32 DeepSeek wsl2 wsl ruoyi 服务器繁忙 备选 网站 api 调用 示例 银河麒麟桌面操作系统 Kylin OS 国产化 DeepSeek行业应用 Heroku 网站部署 TRAE AutoDL IIS服务器 IIS性能 日志监控 selete 高级IO rpc vasp安装 边缘计算 智能硬件 Linux PID 华为od sqlite TCP服务器 qt项目 qt项目实战 qt教程 openssl 密码学 微信分享 鸿蒙 Image wxopensdk 模拟退火算法 ceph 田俊楠 国标28181 视频监控 监控接入 语音广播 流程 SIP SDP 编辑器 MQTT mosquitto 消息队列 r语言 数据挖掘 数据可视化 数据分析 word图片自动上传 word一键转存 复制word图片 复制word图文 复制word公式 粘贴word图文 粘贴word公式 程序员 ci/cd 机器人 数据库系统 EMQX 通信协议 kafka hibernate list 数据结构 kamailio sip VoIP 根服务器 clickhouse jar 宝塔面板 同步 备份 建站 excel laravel 大模型入门 大模型教程 webrtc remote-ssh sqlserver junit ukui 麒麟kylinos openeuler W5500 OLED u8g2 微服务 chfs ubuntu 16.04 框架搭建 unity3d springboot 火绒安全 云服务器 VPS Nuxt.js Xterminal 需求分析 规格说明书 豆瓣 追剧助手 迅雷 nas 微信小程序 前端框架 RTMP 应用层 反向代理 致远OA OA服务器 服务器磁盘扩容 okhttp CORS 跨域 JAVA Java 雨云 NPS 飞书 孤岛惊魂4 uniapp aws 恒源云 tcp HarmonyOS Next AD域 vSphere vCenter 软件定义数据中心 sddc 单一职责原则 3d 数学建模 服务器数据恢复 数据恢复 存储数据恢复 北亚数据恢复 oracle数据恢复 jmeter 软件测试 网络结构图 HCIE 数通 oneapi 大模型微调 open webui 7z 输入法 echarts YOLOv12 av1 电视盒子 机顶盒ROM 魔百盒刷机 传统数据库升级 银行 大语言模型 LLMs Dify 向日葵 asp.net大文件上传 asp.net大文件上传下载 asp.net大文件上传源码 ASP.NET断点续传 asp.net上传文件夹 asp.net上传大文件 .net core断点续传 远程 执行 sshpass 操作 华为认证 网络工程师 移动云 MS Materials gateway Clion Nova ResharperC++引擎 Centos7 远程开发 多进程 外网访问 内网穿透 端口映射 Headless Linux mongodb XCC Lenovo 安全架构 AISphereButler tcpdump shell embedding Windsurf visualstudio zookeeper SSL 域名 skynet WSL win11 无法解析服务器的名称或地址 Agent armbian u-boot LORA NLP Trae IDE AI 原生集成开发环境 Trae AI 企业微信 Linux24.04 deepin npm Cursor 驱动开发 硬件工程 嵌入式实习 RustDesk自建服务器 rustdesk服务器 docker rustdesk 黑客技术 报错 URL ftp web pyqt 微信小程序域名配置 微信小程序服务器域名 微信小程序合法域名 小程序配置业务域名 微信小程序需要域名吗 微信小程序添加域名 EasyConnect Cline LLM Web APP Streamlit pygame 小游戏 五子棋 hadoop big data opensearch helm 服务器主板 AI芯片 ssrf 失效的访问控制 HTML audio 控件组件 vue3 audio音乐播放器 Audio标签自定义样式默认 vue3播放音频文件音效音乐 自定义audio播放器样式 播放暂停调整声音大小下载文件 MI300x 交互 openwrt ux 多线程 vscode1.86 1.86版本 ssh远程连接 SSE zabbix open Euler dde 统信UOS Python 网络编程 聊天服务器 套接字 TCP 客户端 Socket asm xrdp 软件工程 unix string模拟实现 深拷贝 浅拷贝 经典的string类问题 三个swap TrinityCore 魔兽世界 开发环境 SSL证书 sysctl.conf vm.nr_hugepages adobe pdf 群晖 文件分享 中间件 iis VSCode odoo 服务器动作 Server action 雨云服务器 僵尸进程 FTP 服务器 崖山数据库 YashanDB 源码剖析 rtsp实现步骤 流媒体开发 Ubuntu 24.04.1 轻量级服务器 NFS redhat VMware安装Ubuntu Ubuntu安装k8s mysql离线安装 ubuntu22.04 mysql8.0 高效日志打印 串口通信日志 服务器日志 系统状态监控日志 异常记录日志 毕设 ollama下载加速 raid5数据恢复 磁盘阵列数据恢复 银河麒麟操作系统 远程过程调用 Windows环境 firewalld 直播推流 服务器部署ai模型 hive Hive环境搭建 hive3环境 Hive远程模式 rsyslog ipython 缓存 三级等保 服务器审计日志备份 FTP服务器 v10 镜像源 软件 微信公众平台 risc-v flash-attention C语言 软考 权限 流式接口 联想开天P90Z装win10 DigitalOcean GPU服务器购买 GPU服务器哪里有 GPU服务器 bootstrap ecmascript nextjs reactjs 压力测试 tailscale derp derper 中转 飞牛NAS 飞牛OS MacBook Pro 网工 camera Arduino 电子信息 Ubuntu Server Ubuntu 22.04.5 IDEA bonding 链路聚合 Reactor 设计模式 C++ idm 课程设计 MCP server C/S LLM windows日志 Unity Dedicated Server Host Client 无头主机 stm32项目 数据库架构 数据管理 数据治理 数据编织 数据虚拟化 iDRAC R720xd 命名管道 客户端与服务端通信 策略模式 单例模式 Linux awk awk函数 awk结构 awk内置变量 awk参数 awk脚本 awk详解 能力提升 面试宝典 技术 IT信息化 agi gpu算力 ios 磁盘监控 iot midjourney AI写作 前后端分离 netty go 服务器无法访问 ip地址无法访问 无法访问宝塔面板 宝塔面板打不开 XFS xfs文件系统损坏 I_O error 佛山戴尔服务器维修 佛山三水服务器维修 file server http server web server 集成学习 集成测试 服务器配置 生物信息学 mcu gitea FunASR ASR Docker Hub docker pull daemon.json SSH 服务 SSH Server OpenSSH Server 技术共享 我的世界 我的世界联机 数码 虚拟机 pyautogui 文件系统 路径解析 navicat 我的世界服务器搭建 加解密 Yakit yaklang 软链接 硬链接 无人机 ROS 自动驾驶 王者荣耀 干货分享 黑客工具 密码爆破 执法记录仪 智能安全帽 smarteye cnn DenseNet less 流量运营 CrewAI log4j 小智AI服务端 xiaozhi TTS onlyoffice 信号处理 AD 域管理 prompt elk eclipse mamba Vmamba bot Docker efficientVIT YOLOv8替换主干网络 TOLOv8 BMC IPMI 带外管理 ui Xinference RAGFlow GCC Linux环境 GoogLeNet CH340 串口驱动 CH341 uart 485 cd 目录切换 Erlang OTP gen_server 热代码交换 事务语义 RAGFLOW RAG 检索增强生成 文档解析 大模型垂直应用 图像处理 ubuntu24 vivado24 freebsd glibc 远程控制 rustdesk bcompare Beyond Compare 模拟器 教程 apt 国内源 llama.cpp dns是什么 如何设置电脑dns dns应该如何设置 在线预览 xlsx xls文件 在浏览器直接打开解析xls表格 前端实现vue3打开excel 文件地址url或接口文档流二进 tensorflow .net mvc断点续传 怎么卸载MySQL MySQL怎么卸载干净 MySQL卸载重新安装教程 MySQL5.7卸载 Linux卸载MySQL8.0 如何卸载MySQL教程 MySQL卸载与安装 AI作画 selenium xpath定位元素 Unity插件 k8s集群资源管理 云原生开发 iventoy VmWare OpenEuler Open WebUI 测试用例 功能测试 剧本 烟花代码 烟花 元旦 强化学习 程序 linux安装配置 个人博客 xml kali 共享文件夹 lsb_release /etc/issue /proc/version uname -r 查看ubuntu版本 RoboVLM 通用机器人策略 VLA设计哲学 vlm fot robot 视觉语言动作模型 具身智能 Ark-TS语言 技能大赛 visual studio code 端口测试 ros2 moveit 机器人运动 EMUI 回退 降级 升级 Ubuntu 24 常用命令 Ubuntu 24 Ubuntu vi 异常处理 高效远程协作 TrustViewer体验 跨设备操作便利 智能远程控制 cmos 中兴光猫 换光猫 网络桥接 自己换光猫 linux环境变量 实习 rtsp服务器 rtsp server android rtsp服务 安卓rtsp服务器 移动端rtsp服务 大牛直播SDK ArkUI 多端开发 智慧分发 应用生态 鸿蒙OS 大模型面经 大模型学习 edge浏览器 n8n dity make 安卓 工业4.0 springcloud 鸿蒙系统 阻塞队列 生产者消费者模型 服务器崩坏原因 网站搭建 serv00 jetty undertow 灵办AI ros Linux无人智慧超市 LInux多线程服务器 QT项目 LInux项目 单片机项目 链表 grafana 微信开放平台 微信公众号配置 rime 游戏开发 SEO hexo Jellyfin VMware安装mocOS VMware macOS系统安装 流水线 脚本式流水线 显示管理器 lightdm gdm 单元测试 devops 游戏引擎 抗锯齿 gcc 元服务 应用上架 图形化界面 换源 Debian firewall 超融合 裸金属服务器 弹性裸金属服务器 金仓数据库 2025 征文 数据库平替用金仓 gpt crosstool-ng 游戏机 鲲鹏 昇腾 npu nac 802.1 portal trae 毕昇JDK 语音识别 半虚拟化 硬件虚拟化 Hypervisor 多层架构 解耦 LInux micropython esp32 mqtt 智能音箱 智能家居 deekseek ragflow 知识库 docker run 数据卷挂载 交互模式 查询数据库服务IP地址 SQL Server 分析解读 proxy模式 postgresql pgpool 本地知识库部署 DeepSeek R1 模型 业界资讯 虚拟局域网 网络攻击模型 code-server SVN Server tortoise svn dba 算力 政务 分布式系统 监控运维 Prometheus Grafana Python基础 Python教程 Python技巧 Radius HAProxy dify 深度求索 私域 gpt-3 文心一言 环境配置 ABAP IM即时通讯 剪切板对通 HTML FORMAT Claude 银河麒麟高级服务器 外接硬盘 Kylin 信号 物联网开发 eNSP 网络规划 VLAN 企业网络 显卡驱动 AnythingLLM AnythingLLM安装 outlook Kali 蓝桥杯 腾讯云大模型知识引擎 小艺 Pura X k8s资源监控 annotations自动化 自动化监控 监控service 监控jvm 做raid 装系统 实战案例 Java Applet URL操作 服务器建立 Socket编程 网络文件读取 序列化反序列化 双系统 直流充电桩 充电桩 主从复制 rust腐蚀 阿里云ECS MacMini Mac 迷你主机 mini Apple 网络用户购物行为分析可视化平台 大数据毕业设计 宠物 毕业设计 免费学习 宠物领养 宠物平台 网络穿透 can 线程池 HarmonyOS ruby bug 虚幻 线程 ssh远程登录 P2P HDLC VR手套 数据手套 动捕手套 动捕数据手套 OD机试真题 华为OD机试真题 服务器能耗统计 css linux上传下载 QT 5.12.12 QT开发环境 Ubuntu18.04 健康医疗 互联网医院 GRUB引导 Linux技巧 dns docker搭建nacos详解 docker部署nacos docker安装nacos 腾讯云搭建nacos centos7搭建nacos DevEco Studio springboot远程调试 java项目远程debug docker远程debug java项目远程调试 springboot远程 USB网络共享 Google pay Apple pay autodl Playwright 自动化测试 编程 vmware 卡死 RAID RAID技术 磁盘 存储 opcua opcda KEPServer安装 uv rclone AList webdav fnOS 浏览器开发 AI浏览器 ssh漏洞 ssh9.9p2 CVE-2025-23419 性能分析 db sonoma 自动更新 繁忙 解决办法 替代网站 汇总推荐 AI推理 CDN AI代码编辑器 matplotlib Linux的基础指令 etl wps yaml Ultralytics 可视化 keepalived ArcTS 登录 ArcUI GridItem arkUI OpenSSH 自定义客户端 SAS safari 系统 大数据平台 chrome devtools chromedriver rocketmq 历史版本 下载 安装 wsgiref Web 服务器网关接口 flink nfs 信息可视化 网页设计 rnn xcode 华为机试 大大通 第三代半导体 碳化硅 回显服务器 UDP的API使用 合成模型 扩散模型 图像生成 Windows ai工具 java-rocketmq jina ardunio BLE etcd 数据安全 RBAC wireshark linux驱动开发 webstorm 视觉检测 frp GIS 遥感 WebGIS nvidia Docker引擎已经停止 Docker无法使用 WSL进度一直是0 镜像加速地址 wordpress 无法访问wordpess后台 打开网站页面错乱 linux宝塔面板 wordpress更换服务器 perf 金融 seatunnel ue4 着色器 ue5 OpenHarmony 真机调试 项目部署到linux服务器 项目部署过程 IMX317 MIPI H265 VCU 本地部署 composer CVE-2024-7347 rag ragflow 源码启动 产测工具框架 IMX6ULL 管理框架 Kylin-Server 服务器安装 语法 iperf3 带宽测试 gradle h.264 ip命令 新增网卡 新增IP 启动网卡 Logstash 日志采集 黑苹果 网卡的名称修改 eth0 ens33 fd 文件描述符 sdkman cpp-httplib sequoiaDB 开发 KylinV10 麒麟操作系统 Vmware cuda cudnn anaconda milvus 捆绑 链接 谷歌浏览器 youtube google gmail WebRTC 用户缓冲区 web3 模拟实现 图形渲染 prometheus数据采集 prometheus数据模型 prometheus特点 SenseVoice lio-sam SLAM IPMITOOL 硬件管理 相机 EtherCAT转Modbus ECT转Modbus协议 EtherCAT转485网关 ECT转Modbus串口网关 EtherCAT转485协议 ECT转Modbus网关 IMM iBMC UltraISO alias unalias 别名 cocoapods threejs 3D 混合开发 环境安装 JDK regedit 开机启动 可信计算技术 HiCar CarLife+ CarPlay QT RK3588 yolov8 CLion 环境迁移 实时互动 Node-Red 编程工具 流编程 VMware创建虚拟机 视频编解码 音乐库 飞牛 实用教程 python3.11 dash 正则表达式 ubuntu24.04.1 tidb GLIBC 源码 webgl bat 端口 查看 ss centos-root /dev/mapper yum clean all df -h / du -sh 工作流 workflow 考研 在线office 僵尸世界大战 游戏服务器搭建 远程看看 远程协助 京东云 知识图谱 基础入门 sqlite3 Anolis nginx安装 linux插件下载 cpu 实时 使用 私有化 ldap trea idea IPv4 子网掩码 公网IP 私有IP SSH 密钥生成 SSH 公钥 私钥 生成 linux 命令 sed 命令 chrome 浏览器下载 chrome 下载安装 谷歌浏览器下载 mariadb ShenTong 架构与原理 epoll 自动化任务管理 开机自启动 企业网络规划 华为eNSP easyui langchain 多个客户端访问 IO多路复用 TCP相关API MySql 移动魔百盒 代理 USB转串口 harmonyOS面试题 大文件分片上传断点续传及进度条 如何批量上传超大文件并显示进度 axios大文件切片上传详细教 node服务器合并切片 vue3大文件上传报错提示错误 大文件秒传跨域报错cors 压测 ECS 邮件APP 免费软件 yum源切换 更换国内yum源 宕机切换 服务器宕机 键盘 Linux find grep vr lua vue-i18n 国际化多语言 vue2中英文切换详细教程 如何动态加载i18n语言包 把语言json放到服务器调用 前端调用api获取语言配置文件 代理服务器 DOIT 四博智联 防火墙 NAT转发 NAT Server aarch64 编译安装 HPC 域名服务 DHCP 符号链接 配置 mq 性能测试 PVE 常用命令 文本命令 目录命令 AI-native Docker Desktop 树莓派 VNC win服务器架设 windows server deepseek r1 thingsboard 迁移指南 办公自动化 自动化生成 pdf教程 make命令 makefile文件 相差8小时 UTC 时间 css3 sentinel iphone iftop 网络流量监控 状态模式 g++ g++13 影刀 #影刀RPA# 状态管理的 UDP 服务器 Arduino RTOS 镜像 服务器管理 配置教程 网站管理 arcgis Ubuntu DeepSeek DeepSeek Ubuntu DeepSeek 本地部署 DeepSeek 知识库 DeepSeek 私有化知识库 本地部署 DeepSeek DeepSeek 私有化部署 Typore UOS1070e UDP 运维监控 DNS leetcode 推荐算法 Attention 服务器时间 qemu libvirt figma 网络爬虫 增强现实 沉浸式体验 应用场景 技术实现 案例分析 AR ping++ visual studio DocFlow 上传视频至服务器代码 vue3批量上传多个视频并预览 如何实现将本地视频上传到网页 element plu视频上传 ant design vue vue3本地上传视频及预览移除 虚幻引擎 论文阅读 mm-wiki搭建 linux搭建mm-wiki mm-wiki搭建与使用 mm-wiki使用 mm-wiki详解 自动化编程 uni-file-picker 拍摄从相册选择 uni.uploadFile H5上传图片 微信小程序上传图片 嵌入式Linux IPC hosts gnu deep learning VS Code 网络建设与运维 网络搭建 神州数码 神州数码云平台 云平台 TrueLicense grub 版本升级 扩容 searxng 网络药理学 生信 PPI String Cytoscape CytoHubba 车载系统 大模型推理 Ubuntu共享文件夹 共享目录 Linux共享文件夹 磁盘镜像 服务器镜像 服务器实时复制 实时文件备份 docker命令大全 程序员创富 nlp minecraft neo4j 分布式训练 西门子PLC 通讯 本地部署AI大模型 MVS 海康威视相机 聚类 ai小智 语音助手 ai小智配网 ai小智教程 esp32语音助手 diy语音助手 EtherNet/IP串口网关 EIP转RS485 EIP转Modbus EtherNet/IP网关协议 EIP转RS485网关 EIP串口服务器 dock 加速 风扇控制软件 CentOS Stream CentOS 基础环境 ubuntu20.04 开机黑屏 存储维护 NetApp存储 EMC存储 匿名管道 人工智能生成内容 沙盒 word 拓扑图 多路转接 docker搭建pg docker搭建pgsql pg授权 postgresql使用 postgresql搭建 内网服务器 内网代理 内网通信 VM搭建win2012 win2012应急响应靶机搭建 攻击者获取服务器权限 上传wakaung病毒 应急响应并溯源 挖矿病毒处置 应急响应综合性靶场 openstack Xen Redis Desktop 热榜 项目部署 wpf xshell termius iterm2 IO模型 数据仓库 数据库开发 database spark HistoryServer Spark YARN jobhistory 信创 信创终端 中科方德 服务网格 istio js DBeaver kerberos Cookie seleium 目标跟踪 OpenVINO 推理应用 TCP协议 鸿蒙开发 移动开发 C# MQTTS 双向认证 emqx PX4 SRS 流媒体 直播 系统开发 binder framework 源码环境 软负载 渗透 fast curl wget 本地化部署 大模型应用 AI Agent 字节智能运维 搭建个人相关服务器 IO 离线部署dify swoole 玩机技巧 软件分享 软件图标 docker部署翻译组件 docker部署deepl docker搭建deepl java对接deepl 翻译组件使用 Qwen2.5-VL vllm AP配网 AK配网 小程序AP配网和AK配网教程 WIFI设备配网小程序UDP开 rpa 内网环境 飞牛nas fnos triton 模型分析 欧标 OCPP 嵌入式系统开发 Deepseek-R1 私有化部署 推理模型 x64 SIGSEGV xmm0 远程服务 粘包问题 conda配置 conda镜像源 李心怡 Linux的权限 大模型部署 docker部署Python 产品经理 MDK 嵌入式开发工具 论文笔记 sublime text