• 施磊老师基于muduo网络库的集群聊天服务器(五)

施磊老师基于muduo网络库的集群聊天服务器(五)

2025-04-27 19:00:36 0 阅读

文章目录

  • 添加好友业务
    • 实现的功能-简单实现
    • 功能不完善
    • 表设计-每个表对应一个单独的处理文件
    • 业务逻辑:-显然不好, 可以改进
    • 为什么功能少
    • 优化
    • SQL联合查询语句
    • 代码结构
    • 测试
    • 问题
  • 群组业务
    • 主要功能
    • 表设计
    • 多表查询:
    • `Group` 类
    • `GroupUser` 类
    • `GroupModel`(数据访问层)
    • 添加群聊业务
  • 群组阶段面试问题
        • 1. **项目介绍怎么讲**
        • 2. **面试官常问点**
        • 3. **容易翻车的地方**
        • 4. **加分点**
        • 5. **别忘了这些细节**
  • 对于c++, 业务不重要!!!
      • **为什么 C++ 更适合做底层,不是业务逻辑?**
  • 至此, 服务器业务代码完毕

添加好友业务

实现的功能-简单实现

基于 控制台的 好友显示

  1. 用户登录后,服务器返回好友列表信息,用户可以与好友聊天。
  2. 添加好友操作通过客户端发送请求到服务器,服务器将用户关系写入数据库的friend表。

功能不完善

本项目并没有非常的严格的, 必须是好友才能聊天, 只需要知道用户 id 和 name, 就能聊天----有能力可以进行改进

表设计-每个表对应一个单独的处理文件

friend表只包含两个字段:user_idfriend_id。通过联合主键确保同一好友关系不会重复。

业务逻辑:-显然不好, 可以改进

用户可以直接添加好友,不需要对方同意。添加好友时,user_idfriend_id会被插入到数据库中。查询好友时,通过数据库的联合查询返回好友的详细信息,包括ID、名字和在线状态(不返回密码)

为什么功能少

C和C++并不像Java或PHP那样内置很多方便的框架和工具来快速处理复杂的业务逻辑。C/C++更偏向底层操作,开发人员需要自己管理更多的细节(如数据库连接、查询等),这会影响功能的扩展。

优化

考虑到客户端登录后好友列表一般不会变化,服务器可以在用户登录时返回好友列表,并将该列表保存在客户端,避免每次登录都从服务器获取。—降低服务器压力

如果有修改, 在下次上线 进行修改

SQL联合查询语句

通过SQL联合查询来获取用户的好友信息,避免重复查询

内连接查询类型:

  • 只返回两个表中匹配的记录。
  • 如果某一表中没有匹配的记录,则不会出现在结果中。
select a.id a.name a.state from user a inner join friend b on b.friendid = a.id where b.userid=%d

LEFT JOIN(左连接):

  • 返回左表中的所有记录,即使右表中没有匹配的记录。

  • 如果右表中没有匹配的记录,结果中对应的字段为 NULL

  • SELECT u.id, u.name, f.friendid
    FROM user u
    LEFT JOIN friend f ON u.id = f.friendid;
    

代码结构

include/public.hpp

ADD_FRIEND_MSG // 添加好友

include/server/chatservice.hpp

// 处理添加好友业务
    void addFriend(const TcpConnectionPtr &conn, json &js, Timestamp time); // conn用来维护用户与其网络连接之间的映射关系 , 快速找到某个用户的连接

include/server/friendmodel.hpp

#ifndef  ADD_FRIEND_H
#define ADD_FRIEND_H
#include "user.hpp"
#include 

// 维护好友信息的操作接口方法
class FriendModel
{
public:
    // 添加好友
    void insert(int userid, int friendid);

    // 返回好友列表 要显示好友的信息
    // 两个表的 联合查询
    vector query(int userid);

};


#endif

src/server/friendmodel.cpp

#include "friendmodel.hpp"
#include "db.h"

// 添加好友
void FriendModel::insert(int userid, int friendid)
{
    // 1. 创建sql语句
    char sql[1024] = {0};
    sprintf(sql, "insert into friend (userid, friendid) values (%d, %d)", userid, friendid);

    // 2. 执行sql语句
    MySQL mysql;
    if (mysql.connect())
    {
        mysql.update(sql);
    }
}

// 返回好友列表 要显示好友的信息
// 两个表的 联合查询
vector FriendModel::query(int userid)
{
    // 1. 创建sql语句
    char sql[1024] = {0};
    sprintf(sql, "select a.id, a.name, a.state from user a inner join friend b on b.friendid = a.id where b.userid = %d", userid); 

    // 2. 执行sql语句
    MySQL mysql;
    if (mysql.connect())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            // 3. 解析结果
            MYSQL_ROW row;
            vector vec;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                User user;
                user.setId(atoi(row[0]));
                user.setName(row[1]);
                user.setState(row[2]);
                vec.push_back(user);
            }
            mysql_free_result(res);
            return vec;
        }
    }
    return vector();  //比vec好点
}

include/server/chatservice.hpp

#include "friendmodel.hpp"

// 好友操作对象
    FriendModel _friendModel;

src/server/chatservice.cpp

//绑定业务
_msghandlermap.insert({ADD_FRIEND_MSG, std::bind(&ChatService::addFriend, this, _1, _2, _3)});


//登陆成功里加
// 查询好友列表并返回
vector uservec = _friendmodel.query(id);
if(!uservec.empty())
{
    // response["friends"] = uservec; // 这是不行的, 因为是自定义类型
    // map也不行, 因为map的value 不确定
    vector vec;
    for(auto &user:uservec)
    {
        json js;
        js["id"] = user.getId();
        js["name"] = user.getName();
        js["state"] = user.getState();
        vec.push_back(js.dump());
    }
    response["friends"] = vec; // 好友列表
}


// 添加好友业务
// 处理添加好友业务 带msgid
void ChatService::addFriend(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int id = js["id"].get();
    int friendid = js["friendid"].get();
    // 添加好友   显示好友信息 在登陆成功那里
    _friendmodel.insert(id, friendid);

}

测试

{"msgid":1,"id":22,"password":"101010"}
{"msgid":6,"id":22,"friendid":23}
{"msgid":6,"id":22,"friendid":25}

//客户端正常退出
{"msgid":1,"id":22,"password":"101010"}

问题

代码现在有个问题, 服务器异常退出, 用户状态可能没有改变, 还是online, 当再次连接时, 用户无法重复登录, 而且 记录在线用户信息的 map 也没有这个用户, 就会导致 即使此时 客户端断开连接, 也无法 下线

群组业务

主要功能

创建群组:群组管理员创建一个新的群组,群名唯一,描述可选。每次创建群组时,数据库中会插入新的记录。群组的 ID 会自动生成,插入时会返回并更新到相应的群组对象。

加入群组:用户加入群组时,会向 group user 表中插入一条记录,记录该用户在某个群组中的身份(如管理员或普通成员)。group user 表的联合主键是 group IDuser ID,确保每个用户在同一群组中只有一条记录。

群聊功能:通过查询群组中的其他成员,将消息转发给他们。这里使用数据库的联合查询,查询指定群组内所有成员的 ID 和角色,来确定要转发消息的对象。

功能目标:

  • 支持用户之间进行群聊交流
  • 用户可以创建群组、加入群组、群聊通信

设计前提:

  • 一个用户可以属于多个群组。
  • 一个群组可以包含多个用户。
  • 群组内成员可能有不同的角色(如管理员)

表设计

allgroup 表:存储群组信息(id、name、desc(群描述))。

字段:

  • id: 群组主键,自增。
  • groupname: 群名(唯一)。
  • groupdesc: 群描述。

groupuser 表:记录用户和群组的关系,包含 groupiduseridgrouprole(成员身份)。

字段:

  • groupid: 所属群组ID。
  • userid: 成员用户ID。
  • grouprole: 在群内的角色(如 creatornormal)。

主键为联合主键(groupid, userid)防止重复加群。

多表查询:

为了提高效率,尽量在单次数据库查询中完成所有相关数据的获取,而不是分多次查询。使用内连接(INNER JOIN)进行联合查询,获取用户所在群组的详细信息以及群组内成员的详细信息。

所以使用一个 vector 存储 groupuser

大型项目 会采用 数据库 连接池 提高效率

避免“查group ID后,再查group info,再查group members”的多次循环查法

Group

  • 表示一个群组,包含群信息及成员列表。
  • 成员变量:
    • id, groupname, groupdesc
    • vector users:群内成员列表

include/server/group.hpp

// group的ORM类

#ifndef GROUP_HPP
#define GROUP_HPP

#include 
#include 
using namespace std;
#include "groupuser.hpp"

class Group
{
    public:
    // 群组的构造函数
    Group(int id=-1, string name="", string desc="")
    {
        this->id = id;
        this->name = name;
        this->desc = desc;
    }

    void setId(int id)
    {
        this->id = id;
    }
    void setName(string name)
    {
        this->name = name;
    }
    void setDesc(string desc)
    {
        this->desc = desc;
    }
    int getId()
    {
        return this->id;
    }
    string getName()
    {
        return this->name;
    }
    string getDesc()
    {
        return this->desc;
    }
    // 群组的成员列表
    vector &getUsers()
    {
        return this->users;
    }


private:
    int id; // 群组id
    string name; // 群组名称
    string desc; // 群组描述
    vector users; // 群组成员id列表

};



#endif

GroupUser

  • 继承自 User 类,增加 grouprole 字段。
  • 表示“某个群内”的一个用户。
  • 方便在群成员列表中体现其角色信息。

群成员不仅要有用户信息,还需知道其在群内身份。

继承 + 扩展字段是一种清晰可维护的做法。

include/server/groupuser.hpp

#ifndef GROUPUSER_H
#define GROUPUSER_H

#include 
using namespace std;
#include "user.hpp"

// 群组用户, 多了一个角色属性, 从User类继承
class GroupUser: public User
{
public:
    void setRole(string role)
    {
        this->role = role;
    }
    string getRole()
    {
        return this->role;
    }

private:
    string role; // 群组角色
    
};

#endif

GroupModel(数据访问层)

1. 创建群组 createGroup

  • 插入 allgroup 表。
  • 获取生成的自增ID,填回 Group 对象。
  • 默认将创建者添加到 groupuser 表,角色为 creator

2. 加入群组 addGroup

  • 插入 groupuser 表,角色为 normal
  • 若联合主键存在,避免重复插入。

3. 查询用户所有群组及成员信息 queryGroups

  • 第一步: 查询用户所在群的基本信息(联合查询 groupuser + allgroup)。
  • 第二步: 对每个群,再查询其所有成员(联合查询 groupuser + user)。
  • 构建完整的 vector,其中每个 Group 包含 vector 成员。

查询优化思路:

  • 利用 多表联合查询 一次性获取结构化数据,减少数据库连接次数。
  • 避免“查group ID后,再查group info,再查group members”的多次循环查法。

4. 查询某个群内除自己外的所有成员 ID(用于群聊转发)

  • 用于群聊时,找出接收方用户ID。
  • SQL:select userid from groupuser where groupid = ? and userid != ?

include/server/groupmodel.hpp

#ifndef GROUPMODEL_HPP
#define GROUPMODEL_HPP

#include "group.hpp"

class GroupModel
{
    public:
    bool createGroup(Group &group); // 创建群组

    // 加入群组
    bool addGroup(int groupid, int userid, string role);

    // 查询用户所在群组
    vector queryGroups(int userid);

    // 根据指定群组id查询群组用户id列表, 除了自己, 主要用户群聊业务
    vector queryGroupUsers(int userid, int groupid);
};
#endif

src/server/groupmodel.cpp

查询用户所在id 的 函数, 可以优化为 只进行一次 mysql查询, 使用三表联合查询

#include "groupmodel.hpp"
#include 


bool GroupModel::createGroup(Group &group) // 创建群组
{   
    // sql语句
    char sql[1024] = {0};
    sprintf(sql, "insert into allgroup(groupname, groupdesc) values('%s', '%s')",
            group.getName().c_str(), group.getDesc().c_str());

    // 连接数据库
    MySQL mysql;
    if (mysql.connect())
    {
        if (mysql.update(sql))
        {
            // 获取插入的id
            group.setId(mysql_insert_id(mysql.getConnection()));
            return true;
        }
    }
    return false;
}

// 加入群组
bool GroupModel::addGroup(int groupid, int userid, string role)
{
    // sql语句
    char sql[1024] = {0};
    sprintf(sql, "insert into groupuser(groupid, userid, grouprole) values(%d, %d, '%s')",
            groupid, userid, role.c_str());

    // 连接数据库
    MySQL mysql;
    if (mysql.connect())
    {
        if (mysql.update(sql))
        {
            return true;
        }
    }
    return false;
}

// 查询用户所在群组---联合查询, 直接取出群组的 全部信息
// 根据用户id查询群组id, 再根据群组id查询群组信息
vector GroupModel::queryGroups(int userid)
{
    // 1.先查询用户所在的所有群组的 群组信息
    // sql语句
    char sql[1024] = {0};
    sprintf(sql, "select a.id, a.groupname, a.groupdesc from allgroup a inner join groupuser b on a.id = b.groupid where b.userid = %d", userid);

    // 连接数据库
    MySQL mysql;
    vector groupVec; // 存储群组信息以及群组用户信息
    if (mysql.connect())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {

            while (MYSQL_ROW row = mysql_fetch_row(res))
            {
                Group group;
                group.setId(atoi(row[0]));
                group.setName(row[1]);
                group.setDesc(row[2]);
                groupVec.push_back(group);
            }
            mysql_free_result(res);
        }
        // 2.查询每个群组的其他用户信息---群组用户id列表
        for (auto &group : groupVec) // 注意这里是引用, 不能用auto group : groupVec
        {
            sprintf(sql, "select a.id,a.name, a.state,b.grouprole from user a inner join groupuser b on a.id = b.userid where b.groupid = %d", group.getId());
            MYSQL_RES *res = mysql.query(sql);
            if (res != nullptr)
            {
                while (MYSQL_ROW row = mysql_fetch_row(res))
                {
                    GroupUser user;
                    user.setId(atoi(row[0]));
                    user.setName(row[1]);
                    user.setState(row[2]);
                    user.setRole(row[3]); // 群组角色
                    // 将用户添加到群组对象中
                    group.getUsers().push_back(user);
                }
                mysql_free_result(res);
            }
        }

        return groupVec;
    }

    return vector();
}


// 根据指定群组id查询群组用户id列表, 除了自己
// 群聊转发业务!!!, 通过群组id查询群组用户id列表
vector GroupModel::queryGroupUsers(int userid, int groupid)
{
    // sql语句
    char sql[1024] = {0};
    // 经过上面的查询用户所在群组的函数, 每个群组的用户id都已经存储在了数据库中
    sprintf(sql, "select userid from groupuser where groupid = %d and userid != %d", groupid, userid);

    // 连接数据库
    MySQL mysql;
    vector userVec; // 存储群组用户id列表
    if (mysql.connect())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            while (MYSQL_ROW row = mysql_fetch_row(res))
            {
                userVec.push_back(atoi(row[0]));
            }
            mysql_free_result(res);
            return userVec;
        }
    }
    return vector();
}

添加群聊业务

include/public.hpp

CREATE_GROUP_MSG, // 创建群组
ADD_GROUP_MSG, // 添加群组
GROUP_CHAT_MSG, // 群聊

include/server/chatservice.hpp

    // 处理群组业务
    GroupModel _groupModel;
    // 处理创建群组业务
    void createGroup(const TcpConnectionPtr &conn, json &js, Timestamp time);

    // 处理添加群组业务
    void addGroup(const TcpConnectionPtr &conn, json &js, Timestamp time);

    // 处理群组聊天业务
    void groupChat(const TcpConnectionPtr &conn, json &js, Timestamp time);

src/server/chatservice.cpp

// 处理创建群组业务
void ChatService::createGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int uerid = js["id"].get();  // 这是 哪个用户要创建群组,  不是群组id
    string groupname = js["groupname"];
    string groupdesc = js["groupdesc"];

    // 存储新创建的群组信息-----此时还未添加到 数据库, 群id还未知
    Group group(-1, groupname, groupdesc);

    if(_groupModel.createGroup(group))
    {
        // 创建群后, 存储群组创建人 信息
        _groupModel.addGroup(group.getId(), uerid, "creator");
        // 服务器响应 可以自行添加
    }
    
    
}

// 处理添加群组业务
void ChatService::addGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int userid = js["id"].get();
    int groupid = js["groupid"].get();

    // 添加群组
    _groupModel.addGroup(groupid, userid, "normal");
}

// 处理群组聊天业务
void ChatService::groupChat(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int userid = js["id"].get();
    int groupid = js["groupid"].get();
    vector userVec = _groupModel.queryGroupUsers(userid, groupid); // 群组用户id列表

    // 群组聊天, 需要将消息转发给群组中的所有用户
    lock_guard lock(_connMutex);
    for(int id : userVec)
    {
        // 用户在线, 就直接转发
        auto it = _userConnMap.find(id);  
        if(it != _userConnMap.end())
        {
            // 在线, 转发消息
            it->second->send(js.dump());
        }
        else
        {
            // 不在线, 存储离线消息
            _offlineMsg.insert(id, js.dump());
        }
    }

}

群组阶段面试问题

1. 项目介绍怎么讲
  • 先说整体架构(客户端 + 服务端 + 数据库)。
  • 强调使用了多线程、网络库(如 muduo)、多表联合查询、离线消息处理等。
  • 群聊业务涵盖:建群、加群、群聊消息转发,突出线程安全处理、connection map、model 层封装等设计。
2. 面试官常问点
  • 你这个项目数据库有哪些表?
    • 答:user、friend、group、group_user、offline_message 等。
  • 数据量多少?
    • 别说 100 万、500 万级别,会被追问“你怎么优化?表怎么拆?”。
    • 建议说“万级”,比如 1~2 万行,合理且真实。
3. 容易翻车的地方
  • 别一张嘴就说“我表里 100 万数据”,会被问爆:
    • 表的索引怎么设计?
    • 是否做了 水平/垂直拆表
    • 有没有用 分库分表工具(如 ShardingSphere)?
  • 数据量吹太大,面试官会质疑你是否真的做过项目。
4. 加分点
  • 主动提到:
    • 使用了线程池+IO线程模型。
    • 使用 STL map 做连接管理,但注意了线程不安全问题,加锁处理。
    • 将代码结构分层(model 层抽象数据逻辑,service 层处理业务,server 层处理网络通信)。
5. 别忘了这些细节
  • CMake 项目结构是否清晰,有没有考虑 include 路径、模块拆分。
  • 聊群组业务时要提到 联合查询(从 group_user 表查成员,转发消息)。
  • 如何做离线消息存储(存到 offline_message 表)。

对于c++, 业务不重要!!!

业务是很灵活的,

为什么 C++ 更适合做底层,不是业务逻辑?

  1. C++ 更适合系统开发:擅长高性能、高并发、底层控制(如网络通信、内存管理、线程控制)。
  2. 业务逻辑适合用其他语言:像 Java、Go 这样的语言,开发效率更高,适合快速实现业务需求。
  3. C++ 做核心模块:像集群聊天中的长连接、消息转发引擎等,由 C++ 提供高性能支持。
  4. Go / Java 处理业务:这些语言适合做用户管理、消息记录等业务层面工作。
  5. 核心关注点:网络通信、协议设计、多线程、IO 模型、内存管理;
  6. 业务逻辑在 C++ 项目里只是“壳子”,重点是“底层系统能力”;
  7. 聊天系统这种项目里,真正难的是搞定高效、稳定、可扩展的通信框架,不是谁跟谁发了个消息。

至此, 服务器业务代码完毕

转移以下代码文件, 把数据层 头文件 的 代码, 放到model文件夹里-----分开数据层与业务层代码

这时就要改cmake, 头文件搜索路径------对应的cpp 同理, 这样完成并修改 cmake

自行修改----不会修改的 等于白看了

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

搜索文章

Tags

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