最新资讯

  • 【Linux网络】基于Reactor反应堆模式的高并发服务器

【Linux网络】基于Reactor反应堆模式的高并发服务器

2026-01-29 19:00:57 栏目:最新资讯 6 阅读

文章目录

  • 1. Reactor 模式
    • 1.1 核心组件
    • 1.2 工作流程(经典单线程Reactor)
  • 2. 设计思路
  • 3. 事件处理器框架
    • 3.1 封装epoll
    • 3.2 Connection基类
    • 3.3 Listener派生类框架
    • 3.3 Channel派生类框架
  • 4. 设计服务器
  • 5. 补充细节
    • 5.1 读事件处理
    • 5.2 写事件处理
    • 5.3 异常事件处理
  • 6. 主函数运行服务器
  • 7. 总结

这篇文章我们将基于 Reactor反应堆模式,使用ET + 非阻塞实现一个epoll服务器

1. Reactor 模式

Reactor 模式是处理高并发网络 I/O 的一种经典事件驱动设计模式。它的核心思想是 通过一个或多个事件循环来统一监听和分发所有 I/O 事件,由一个或少数线程来处理大量并发连接,从而避免为每个连接创建独立线程带来的巨大资源开销。

我们先通过一个生活化的比喻来建立直观感受。

想象一下一家餐厅的服务模式:

  • 传统多线程模式 (Thread-Per-Connection):好比一个顾客配一个专属服务员。从点菜、下单到上菜,这个服务员全程只为这一桌服务。如果后厨做菜慢,服务员也只能等着,无法服务其他顾客。顾客多了,餐厅就需要雇佣大量服务员,人力成本极高。
  • Reactor 模式:更像一家高效运营的现代餐厅。它有一个(或几个)接待员 (Reactor)。接待员的工作不是直接服务顾客,而是站在餐厅中央,时刻关注所有顾客的状态 (事件)
    • 当新顾客进门时 (连接事件),接待员引导其入座。
    • 当某桌顾客举手示意已看好菜单 (可读事件),接待员通知一个空闲的服务员 (Handler) 过去点菜。
    • 当后厨的菜做好了 (数据就绪),接待员再通知服务员去上菜 (可写事件)。

这样,通过少数角色(接待员)高效协调多个服务资源,用很少的服务员就能应对大量的顾客,这就是 Reactor 模式的精髓。

1.1 核心组件

  1. 反应器(Reactor / Dispatcher): 核心的事件循环。它运行在一个或多个线程中,持续监听并分发事件。
  2. 事件多路分解器(Demultiplexer / Synchronous Event Demultiplexer):通常是 selectepoll(Linux)kqueue(BSD/macOS)IOCP(Windows)等系统调用。它负责等待多个 I/O 事件的发生,并在事件就绪时通知 Reactor。它是实现高效的关键。
  3. 事件处理器(EventHandler / Concrete Event Handler): 定义了处理特定事件(如连接建立、数据到达)的接口或回调函数。通常每个网络连接都会对应一个处理器。
  4. 具体事件处理器(ConcreteEventHandler): 实现了业务逻辑,如读取数据、处理请求、发送响应。

1.2 工作流程(经典单线程Reactor)

  1. 初始化: Reactor 将需要监听的事件(如服务器套接字的“连接就绪”事件)注册到多路分解器。
  2. 事件循环
    等待: Reactor 调用多路分解器的 select/epoll_wait 方法,阻塞等待任何注册的事件发生。
    通知: 当有事件就绪(如新连接到达、 socket 可读),多路分解器返回。
    分发: Reactor 遍历就绪的事件,并根据事件类型(读/写/连接)分发给对应的具体事件处理器。
    处理: 具体事件处理器执行非阻塞的 I/O 操作(如 acceptreadwrite)和业务处理。

2. 设计思路

当我们在读取的时候,我们怎么保证我们读到的数据,未来给每一个fd,都要维护起来?

搞清楚这个问题之前,我们需要先说明白:为什么需要为每个fd单独维护数据?

在基于 epoll的事件驱动模型中,程序在一个主循环中等待事件,当某个连接(fd)可读时,才去读取数据。这带来两个问题:

  1. TCP是字节流 :数据像水流一样到达,一次 read 调用可能只收到半条应用层消息、一条完整消息,或者多条消息的碎片。
  2. 事件是离散的epoll 只通知“有数据可读”,但不会通知“有多少”或“是否完整”。程序必须在每次触发读取后,将数据暂存起来,直到累积成一条有意义的、应用层可处理的消息。

如果不为每个 fd 单独维护接收缓冲区,数据就会混杂或丢失,无法正确重组消息。

所以我们要怎么维护每一个fd呢?

每个客户端连接对应一个fd。为了高效处理数据,我们可以为每个fd维护独立的buffer,用于暂存未处理完的数据。

问题:listensocket和普通socket,有区别吗?

监听套接字(listensockfd)和普通连接套接字(normal fd)在本质上都是文件描述符,它们在 epoll的事件驱动模型中被统一看待,但其“就绪”后所对应的操作截然不同。只不过listensockfd将来在‘recv’的时候,用的是accept!!两者统一了!!

因此,不是所有fd都需要维护缓冲区buffer,因为我们的监听套接字fd的读事件只需要接受(accept)新的客户端连接,并不会真的读取数据,而已经建立连接的普通套接字fd才需要进行读写数据,这个时候才需要维护自己的缓冲区。

所以,对于不同的套接字fd有不同的行为,这个时候我们就可以采用继承与多态的做法,我们定义一个基类 Connection,在基类中定义监听套接字listensockfd和普通套接字sockfd都需要的成员变量,再分别定义listensockfd需要的派生类Listener,和sockfd需要的派生类Channel,在对应的派生类中定义各自需要的成员变量,这样我们就可以通过多态来实现不同套接字的不同行为

问题:服务器如何管理/派发就绪的事件? (如新连接到达、 socket 可读或可写)

我们知道,当有文件描述符就绪时,内核会将就绪事件填充到用户提供的 events 数组中,并返回就绪事件的数量。但是我们服务器如何将就绪的事件分发给对应的事件处理器去处理呢?

在前面我们已经打算通过继承和多态来处理不同套接字的不同行为,也就是说,当读事件就绪(新连接到来),我们就要通过Listener派生类来处理就绪的读事件(accept新连接),当普通读写事件就绪,就需要通过Channel派生类来处理就绪的读写事件(recv/send数据到对应fd的缓冲区中)

所以,服务器要想将就绪事件派发给不同的处理器处理,就需要建立服务器和Connection基类之间的关系(多态行为需要基类指针或引用)。因为服务器只能在 events 数组中拿到最直接的文件描述符fd,不能直接拿到对应fd封装的Connection基类

那么这个时候我们服务器就可以选择哈希表这个容器,来建立需要关心的文件描述符fd和对应的Connection基类之间的关系,这样我们就能派发就绪事件给对应的事件处理器

问题:Listener派生类accept接受新连接时,如何将之后返回的通信套接字sockfd(也就是与客户端连接建立成功之后的普通读写套接字)添加到服务器中的哈希表中呢?

为了服务器后续管理,我们需要将所有内核关心的fd添加到哈希表中建立映射。但是哈希表中存储的对象是服务器需要管理的,并不是对应具体事件处理器管理的,那么Listener派生类在接受新连接之后,得到的普通读写套接字,要怎么添加到服务器内管理的哈希表中呢?

这里我们可以在Connection基类中定义一个回指指针,指向服务器,这样我们就可以通过回指指针调用服务器中的接口来添加fd到哈希表中

同样,后面在普通读写事件时,如果发送缓冲区的数据满了,那么此时就不能再向发送缓冲区写入数据,这个时候我们就需要开启对写事件的关心,这就需要通知内核帮我们关心写事件,所以这个时候也可以通过回指指针来调用服务器中的接口从而向内核中添加对写事件的关心。

所以我们需要在Connection基类中定义一个回指指针,而不是只在Listener派生类中定义,因为都需要通过回指指针来调用服务器中的接口


3. 事件处理器框架

3.1 封装epoll

我们先来把epoll相关的函数封装一下

#pragma once

#include 
#include 
#include "Common.hpp"
#include "Log.hpp"

using namespace LogModule;

class Epoller
{
public:
    Epoller() : _epfd(-1)
    {
        // 创建epoll模型
        _epfd = epoll_create(256);
        if (_epfd < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_create error...";
            exit(EPOLL_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "epoll_create success, _epfd: " << _epfd;
    }

    void ModEventHelper(int sockfd, uint32_t events, int op)
    {
        struct epoll_event ev;
        ev.data.fd = sockfd;
        ev.events = events;
        int n = epoll_ctl(_epfd, op, sockfd, &ev);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "epoll_ctl error...";
            return;
        }
        LOG(LogLevel::INFO) << "epoll_ctl success..., sockfd: " << sockfd;
    }

    void AddEvent(int sockfd, uint32_t events)
    {
        ModEventHelper(sockfd, events, EPOLL_CTL_ADD);
    }

    void ModEvent(int sockfd, uint32_t events)
    {
        ModEventHelper(sockfd, events, EPOLL_CTL_MOD);
    }

    void DelEvent(int sockfd)
    {
        int m = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr); // 删除不需要再关心任何事件直接填空指针
        if (m > 0)
        {
            LOG(LogLevel::INFO) << "epoll_ctl remove sockfd success: " << sockfd;
        }
    }

    int WaitEvent(struct epoll_event evs[], int maxnum, int timeout)
    {
        int n = epoll_wait(_epfd, evs, maxnum, timeout);
        if(n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_wait error...";
        }
        else if(n == 0)
        {
            LOG(LogLevel::WARNING) << "epoll_wait timeout...";
        }
        else
        {
            LOG(LogLevel::DEBUG) << "有事件就绪了...,就绪事件的数量n: " << n;
            // 事件派发逻辑我们在服务器中实现
        }
        return n;
    }

    ~Epoller()
    {
        if (_epfd >= 0)
        {
            close(_epfd);
        }
    }

private:
    int _epfd;
};

对于epoll相关函数我们在上一篇文章中已经详细介绍过,并介绍了如何使用,这里就不再过多介绍


3.2 Connection基类

在基类中我们定义派生类都需要的成员变量和函数,但是读写函数以及错误处理都会设置为纯虚函数,派生类中需要怎么处理就自己去重写

#pragma once

#include 

class Reactor;
// 基类
class Connection
{
public:
    Connection():_events(0), _owner(nullptr)
    {}

    virtual void Recver() = 0;
    virtual void Sender() = 0;
    virtual void Excepter() = 0;
    virtual int GetSockfd() = 0;

    void SetEvent(const uint32_t& events)
    {
        _events = events;
    }

    uint32_t GetEvent()
    {
        return _events;
    }

    void SetOwner(Reactor* owner)
    {
        _owner = owner;
    }

    Reactor* GetOwner()
    {
        return _owner;
    }
    
    ~Connection(){}
private:
    uint32_t _events;
    Reactor* _owner;
};

3.3 Listener派生类框架

Listener派生类 只需要关心读事件,并且只需要acceot接受连接,并不需要去从缓冲区中读数据上来,同时我们需要ET模式的非阻塞epoll服务器,那就还需要在构造函数中设置非阻塞,那么我们可以将之前介绍的设置非阻塞的方法放在 Common.hpp 里(前面写网络编程时封装的一个公有接口文件,如:错误码封装、不可拷贝的基类等)

#pragma once

#include 
#include "Epoller.hpp"
#include "Socket.hpp"
#include "Common.hpp"
#include "Connection.hpp"

using namespace SocketModule;

// Listener 专门进行获取新连接
class Listener : public Connection
{
public:
    Listener(int port):_port(port), _listensockfd(std::make_unique<TcpSocket>())
    {
        _listensockfd->BuildTcpSocketMethod(_port);
        SetEvent(EPOLLIN | EPOLLET); // ET模式
        SetNonBlock(_listensockfd->Fd()); // 设置非阻塞
    }

    void Recver() override
    {}

    void Sender() override
    {}
    
    void Excepter() override
    {}

    int GetSockfd() override
    {
        return _listensockfd->Fd();
    }

    ~Listener() {}
private:
    int _port;
    std::unique_ptr<Socket> _listensockfd;
};

Listener派生类 中只需要重写读和获取fd两个接口,另外两个不需要用到。至于具体的读事件处理我们后面再完善


3.3 Channel派生类框架

Channel派生类 需要处理普通的读写事件,因此 Channel派生类 的所有普通读写套接字sockfd都需要自己的缓冲区

#pragma once


#include 
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Connection.hpp"


// 普通sockfd的封装
class Channel : public Connection
{
public:
    Channel(int sockfd, const InetAddr& client):_sockfd(sockfd), _client(client)
    {
        SetNonBlock(_sockfd); // 设置非阻塞
    }

    void Recver() override
    {}

    void Sender() override
    {}
    
    void Excepter() override
    {}

    int GetSockfd() override
    {
        return _sockfd;
    }

    ~Channel() {}
private:
    int _sockfd;
    std::string _inbuffer;
    std::string _outbuffer;
    InetAddr _client;
};

同样关于具体读写以及异常处理我们后面再处理


4. 设计服务器

在服务器中,首先肯定需要创建一个epoll模型,所以需要一个Epoller类型的指针,当然还有我们一直都在用的运行标志位,还有我们前面说过的哈希表,用来管理获取到的fd,同时还要管理就绪的事件,这里我们直接采用静态数组

#pragma once

#include 
#include "Connection.hpp"

class Reactor
{
    static const int evs_num = 128;
private:
    bool IsConnectionEmpty()
    {
        return _connections.empty();
    }

    // 一次循环
    int LoopOnce(int timeout)
    {
        return _epoller_ptr->WaitEvent(_evs, evs_num, timeout);
    }

public:
    Reactor():_epoller_ptr(std::make_unique<Epoller>()), _isrunning(false)
    {}

    void Loop()
    {
        if(IsConnectionEmpty())
            return;

        _isrunning = true;
        int timeout = -1;
        while(_isrunning)
        {
            int n = LoopOnce(timeout);
            Dispatcher(n);
        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = false;
    }
    ~Reactor() {}
private:
    // 1. epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;
    // 2. 是否启动 
    bool _isrunning; 
    // 3. 管理所有的connection,本质是管理未来所有我获取到的fd
    // fd : Connection
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    // 4. 就绪的所有事件
    struct epoll_event _evs[evs_num];
};

在LoopOnce中我们通过epoll_wait进行阻塞式的等待事件就绪(timeout 设置为-1)

注意:这里我们阻塞的目的是高效地等待。让出CPU,避免空转,仅在有事可做时被唤醒。我们之前说的实现非阻塞是指IO事件处理器(负责处理 epoll_wait返回的就绪事件)必须设置为非阻塞。通过 fcntl设置 O_NONBLOCK标志,将 socket 设为非阻塞模式。目的是不延误。确保处理单个fd的I/O时不会阻塞整个事件循环,从而快速服务所有连接。

在LoopOnce中事件就绪返回之后,我们就可以将事件派发给不同的事件处理器去处理

事件派发器代码如下

    // 事件派发器
    void Dispatcher(int n)
    {
        for(int i = 0; i < n; i++)
        {
            int sockfd = _evs[i].data.fd; // 就绪的fd
            uint32_t events = _evs[i].events; // 就绪的事件
            // 1. 将所有的异常处理,统一转化成IO错误 2. 所有的IO异常,统一转换成为一个异常处理函数
            if (events & EPOLLERR) // 出错
                events |= (EPOLLIN | EPOLLOUT); // 将所有的异常处理,统一转化成IO错误
            if (events & EPOLLHUP) // 对端退出
                events |= (EPOLLIN | EPOLLOUT); // 将所有的异常处理,统一转化成IO错误

            // 读事件就绪, 用不用区分是否异常?不用,未来会在IO处理器内部统一处理
            if(events & EPOLLIN)
            {
                // 读事件就绪,还用不用区分是listenfd还是普通socketfd?不用,这里会多态调用自己的事件处理器
                if(IsConnectionExist(sockfd))
                    _connections[sockfd]->Recver();
            }

            if(events & EPOLLOUT)
            {
                // 写事件就绪
                if(IsConnectionExist(sockfd))
                    _connections[sockfd]->Sender();
            }
        }
    }

在事件派发器中我们将所有的异常处理,统一转化成IO错误。为什么这么做?因为我们不仅仅在检测事件就绪时,文件描述符会出错,并且对端退出也会出错,然而我们在进行IO时也会出错,这些错误我们当然可以一个一个处理,但是我们如果统一转化为IO错误,最后在进行统一处理不就要高效简洁一点嘛

另外,我们这里读事件就绪后,就不再需要去判断是新连接到来,还是普通读事件就绪了,因为我们直接可以多态调用自己的事件处理器来处理

服务器需要将我们想要关心的fd和events写入到内核中,让内核帮我们关心,同时还需要添加到哈希表中管理,所以肯定需要增删接口来完成这些工作

    void AddConnection(const std::shared_ptr<Connection>& conn)
    {
        if(IsConnectionExist(conn->GetSockfd()))
        {
            LOG(LogLevel::WARNING) << "conn is exists: " << conn->GetSockfd();
            return;
        }
        
        // 1. conn对应的fd和他要关心的事件,写透到内核中!
        int sockfd = conn->GetSockfd();
        uint32_t events = conn->GetEvent();
        _epoller_ptr->AddEvent(sockfd, events);

        // 2. 设置当前conn的拥有者回指指针
        conn->SetOwner(this);

        // 3. 添加到哈希表中管理
        _connections[sockfd] = conn;
    }

    void DelConnection(int sockfd)
    {
        if(!IsConnectionExist(sockfd))
        {
            LOG(LogLevel::WARNING) << "connection is not exist";
            return;
        }

        // 从内核中移除关心fd
        _epoller_ptr->DelEvent(sockfd);

        // 从哈希表中移除,不再管理
        _connections.erase(sockfd);

        // 关闭fd
        close(sockfd);

        LOG(LogLevel::INFO) << "client quit: " << sockfd;
    }


5. 补充细节

5.1 读事件处理

Listener派生类——接受新连接

新连接就绪了,但是你不能保证只有一个新连接,因此我们需要一次性将所有连接读取上来进行连接

这里我们需要将之前封装的Socket稍微修改一下,我们需要通过错误码errno判断具体的错误原因,因为有可能将底层所有连接读取完时,错误码表示的意思并非是出错了,而是暂时数据还没有就绪,这个时候就需要继续等待新连接到来了,还有可能是暂时被信号中断了,OS优先去执行其他任务了,这个时候我们后续需要继续循环执行。

#define ACCEPT_DONE -1
#define ACCEPT_CONTINUE -2
#define ACCEPT_ERR -3
        int Accept(InetAddr *client) override
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int fd = ::accept(_sockfd, (struct sockaddr*)&peer, &len);
            if (fd < 0)
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    return -1; // 底层没有新连接
                }
                else if(errno == EINTR)
                {
                    return -2; // 被信号中断,继续读取
                }
                else
                {
                    LOG(LogLevel::WARNING) << "accept error";
                    return -3; // 出错
                }
            }
            client->SetAddr(peer);
            return fd;
        }

这里我们只需要不断循环的接受新连接,直到将所有连接获取完毕,因为我们一开始在构造函数就设置了非阻塞,所以并不会阻塞整个进程的执行

    void Recver() override
    {
        InetAddr client;
        // 新连接就绪了,你能保证只有 一个连接到来吗? 我们要一次把所有的连接全部获取上来
        // while, ET, sockfd设置为非阻塞!! ---- listensock本身设置为非阻塞
        while(true)
        {
            int sockfd = _listensockfd->Accept(&client);
            if(sockfd == ACCEPT_DONE)
                break; // 这个时候我们可以保证新连接都获取完了
            else if(sockfd == ACCEPT_CONTINUE)
                continue;
            else if(sockfd == ACCEPT_ERR)
                break; // 真正出错就退出循环不需要再继续
            else
            {
                // 此时连接建立成功,拿到的是普通读写套接字
                // fd默认事件状态(缓冲区为空时):读事件不就绪,写事件就绪
                // 我们需要将普通读写套接字交给内核帮我们关心读事件,写事件默认就绪不需要关心
                std::shared_ptr<Connection> conn = std::make_shared<Channel>(sockfd, client);
                conn->SetEvent(EPOLLIN | EPOLLET); // ET模式

                GetOwner()->AddConnection(conn);
            }
        }
    }

当你连接建立成功,拿到普通读写套接字sockfd时,就需要将sockfd的读事件交给内核帮我们关心,因为fd的默认事件状态,是读事件不就绪,写事件就绪,同时还需要将sockfd添加到哈希表中方便服务器未来管理

Channel派生类——普通读事件

这里我们同样需要不断循环,来把本轮的数据全部读取到用户接受缓冲区上

    // 问题1: 怎么保证我把本轮数据读取完毕? while 循环 --- 本层只解决IO问题 --- done
    // 问题2:即便是你把本轮数据读完,你怎么知道数据就有完整的报文,如果不完整呢?如果是多个报文呢?粘报问题?反序列化 --- 引入协议的
    void Recver() override
    {
        char buffer[SIZE];
        while(true)
        {
            buffer[0] = 0;
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer)-1, 0);
            if(n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if(n == 0)
            {
                Excepter();// 异常处理
                return;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR) // 信号中断
                {
                    continue;
                }
                else
                {
                    Excepter();// 异常处理
                    return;
                }
            }
        }

        if(!_inbuffer.empty())
        {
            // 回调交给上层处理
        }

        if(!_outbuffer.empty())
        {
            Sender();
        }
    }

之前我们说过,把所有异常处理统一转换为IO错误,那么在IO中,我们可以再统一交给异常函数去处理。但是,即便是你把本轮数据读完,你怎么知道数据就有完整的报文,如果不完整呢?如果是多个报文呢?出现粘报问题呢?

所以这里我们需要把用户接受缓冲区的数据交给上层的协议层,来进行对报文的解析拿到一条完整的报文,然后再反序列化得到结构化的数据,此时我们就可以在协议层中进行回调交给应用层来处理数据,应用层处理完数据后将结果回调到协议层,最后协议层再对结果进行反序列化和封装报文,再次回调回来写入用户发送缓冲区

我们之前就已经自己定制过协议,同时还简单实现了应用层的计算器,所以我们这里可以再引入之前自己写的定制协议和网络计算器。

我们先在基类中新增一个回调注册函数

#pragma once

#include 
#include 
#include "Epoller.hpp"
#include "Socket.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"

class Reactor;

using handler_t = std::function<std::string (std::string &)>;

// 基类
class Connection
{
public:
    Connection():_events(0), _owner(nullptr)
    {}

    virtual void Recver() = 0;
    virtual void Sender() = 0;
    virtual void Excepter() = 0;
    virtual int GetSockfd() = 0;

    void SetEvent(const uint32_t& events)
    {
        _events = events;
    }

    uint32_t GetEvent()
    {
        return _events;
    }

    void SetOwner(Reactor* owner)
    {
        _owner = owner;
    }

    Reactor* GetOwner()
    {
        return _owner;
    }

    void RegisterHandler(handler_t handler)
    {
        _handler = handler;
    }
    
    ~Connection(){}
private:
    uint32_t _events;
    Reactor* _owner;
public:
    handler_t _handler;
};

另外,在Listener派生类接受新连接时,将回调函数注册(回调函数的编写可以在Main.cc主函数中)

    void Recver() override
    {
        InetAddr client;
        // 新连接就绪了,你能保证只有 一个连接到来吗? 我们要一次把所有的连接全部获取上来
        // while, ET, sockfd设置为非阻塞!! ---- listensock本身设置为非阻塞
        while(true)
        {
            int sockfd = _listensockfd->Accept(&client);
            if(sockfd == ACCEPT_DONE)
                break; // 这个时候我们可以保证新连接都获取完了
            else if(sockfd == ACCEPT_CONTINUE)
                continue;
            else if(sockfd == ACCEPT_ERR)
                break; // 真正出错就退出循环不需要再继续
            else
            {
                // 此时连接建立成功,拿到的是普通读写套接字
                // fd默认事件状态(缓冲区为空时):读事件不就绪,写事件就绪
                // 我们需要将普通读写套接字交给内核帮我们关心读事件,写事件默认就绪不需要关心
                std::shared_ptr<Connection> conn = std::make_shared<Channel>(sockfd, client);
                conn->SetEvent(EPOLLIN | EPOLLET); // ET模式
                if(_handler != nullptr)
                    conn->RegisterHandler(_handler);
                GetOwner()->AddConnection(conn);
            }
        }
    }

我们之前自己写的协议包含了服务器和客户端两个部分,这里我们只需要实现服务器即可,所以我们可以将之前的客户端获取应答报文以及构建请求报文接口删除,同时修改一下获取请求报文。

在协议中我们可以一次处理一条完整的报文,不断解析完整报文的部分我们可以放在回调函数中

代码如下:

    std::string Execute(std::string &json_package)
    {
        // 将json字符串反序列化
        Request req;
        bool ok = req.Deserialize(json_package);
        if (!ok)
            return std::string();
        // 回调到应用层进行处理
        Response res = _func(req);

        // 将结果序列化
        std::string jsonstr = res.Serialize();

        // 封装报文
        std::string message = Encode(jsonstr);

        return message;
    }

现在我们就可以将用户接受缓冲区中的数据回调交给协议层处理

    void Recver() override
    {
        char buffer[SIZE];
        while(true)
        {
            buffer[0] = 0;
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer)-1, 0);
            if(n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if(n == 0)
            {
                Excepter();// 异常处理
                return;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR) // 信号中断
                {
                    continue;
                }
                else
                {
                    Excepter();// 异常处理
                    return;
                }
            }
        }

        LOG(LogLevel::DEBUG) << "Channel: Inbuffer:
" << _inbuffer;

        if(!_inbuffer.empty())
        {
            // 回调交给上层处理
            _outbuffer += _handler(_inbuffer);
        }

        if(!_outbuffer.empty())
        {
            Sender();
        }
    }

5.2 写事件处理

    void Sender() override
    {
        while(true)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if(n > 0)
            {
                _outbuffer.erase(0, n);
                // 发送缓冲区为空时退出循环
                if(_outbuffer.empty())
                    break;
            }
            else if(n == 0)// 对端关闭
            {
                Excepter();  // 异常处理
                return;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR) // 信号中断
                {
                    continue;
                }
                else
                {
                    Excepter();// 异常处理
                    return;
                }
            }
        }

        // 1. 数据发送完毕
        // 2. 发送条件不具备
        if(!_outbuffer.empty())
        {
            // 此时用户发送缓冲区还有数据,说明内核缓冲区满了,即发送条件不具备
            // 此时开启对写事件的关心
            GetOwner()->EnableReadWrite(_sockfd, true, true);
        }
        else
        {
            // 到这里数据发送完毕
            GetOwner()->EnableReadWrite(_sockfd, true, false);
        }
    }

同样,我们需要不断循环将数据写入内核缓冲区,如果循环结束,我们就需要判断是数据发送完毕还是内核缓冲区已经满了,不能在写了,后者我们就需要让内核帮我们关注写事件。

另外这两种情况下我们都需要让内核帮我们关注读事件,因为我们是ET模式,只要内核缓冲区状态发生变化,就会通知我们读事件就绪,我们必须在读事件就绪时就一次性全部读上来。在这里我们将读取到用户接受缓冲区里的数据回调交给协议层处理,然后把结果回调回来写到用户发送缓冲区中,说明用户接收缓冲区又有空间了,那么我们就需要关注读事件是否就绪。因为只要用户接受缓冲区没满,就需要关注读事件。

所以我们还需要在服务器中实现一个使能读写的接口,让内核帮我们关注读写事件

    void EnableReadWrite(int sockfd, bool enableread, bool enablewrite)
    {
        if (!IsConnectionExist(sockfd))
        {
            LOG(LogLevel::WARNING) << "EnableReadWrite, conn is not exists, sockfd: " << sockfd;
            return;
        }

        uint32_t new_event = EPOLLET | (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT : 0);
        _connections[sockfd]->SetEvent(new_event);
        _epoller_ptr->ModEvent(sockfd, new_event);
    }

5.3 异常事件处理

所以错误都被归总在了异常处理这里

    void Excepter() override
    {
        // 所有的异常,都被我归一到了这个函数内部!!
        GetOwner()->DelConnection(_sockfd);
    }

直接从内核移除关心,然后从哈希表中移除管理,最后关闭文件描述符,而这些我们已经DelConnection这个接口中实现,直接调用即可


6. 主函数运行服务器

至此,我们从下至上实现了一个高效的epoll服务器

主函数中我们需要从上而下构建不同模块的对象

代码如下:

#include 
#include 
#include "Reactor.hpp"
#include "Listener.hpp"
#include "Channel.hpp"
#include "Log.hpp"
#include "Common.hpp"
#include "Protocol.hpp"
#include "NetCal.hpp"

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "Usage: " << argv[0] << " port" << std::endl;
        exit(USAGE_ERR);
    }
    Enable_Console_Log_Strategy();
    uint16_t port = std::stoi(argv[1]);

    // 构建一个业务模块
    std::shared_ptr<Cal> cal = std::make_shared<Cal>();

    // 构建协议对象
    std::shared_ptr<Protocol> protocol = std::make_shared<Protocol>([&cal](Request &req) -> Response
                                                                    { return cal->Execute(req); });
    // 构建Listener对象
    std::shared_ptr<Connection> conn = std::make_shared<Listener>(port);
    conn->RegisterHandler([&protocol](std::string &inbuffer) -> std::string { // 这个匿名函数就是要被Channel回调的
        LOG(LogLevel::DEBUG) << "进入到匿名函数中...";
        std::string response_str;
        while (true)
        {
            std::string package;
            if (!protocol->Decode(inbuffer, &package))
                break;
            // 我敢保证,我的packge一定是一个完整的请求,是字节流的
            response_str += protocol->Execute(package);
        }
        LOG(LogLevel::DEBUG) << "结束匿名函数...: " << response_str;
        return response_str;
    });
    // 构建一个reactor模块
    std::unique_ptr<Reactor> R = std::make_unique<Reactor>();
    R->AddConnection(conn);

    R->Loop();

    return 0;
}

Cal对象:这是应用层业务逻辑的核心,负责执行具体的计算任务。

Protocol对象:这是应用层协议解析器,负责两件关键事情:

  • Decode:将接收到的原始字节流(inbuffer)根据预定规则(如长度、分隔符)拆分成一个个完整的请求包(package)。
  • Execute:它本身不处理业务,而是将拆分好的请求包传递给业务逻辑模块(cal) 进行处理,并获取返回结果。这样做就实现了网络层与业务层的解耦

Listener对象:它封装了监听套接字,负责在指定端口上接受新的客户端连接。它是一个特殊的Connection,即派生类。

注册回调函数:这是事件驱动模型的关键。这里为一个匿名函数(Lambda表达式) 注册到了监听器的数据到达事件上。当这个连接上有数据可读时(用户接收缓冲区上有数据时),Reactor就会自动调用这个函数。

Reactor对象:它是整个服务器的调度中心。服务器内部使用了 epoll 这样的 I/O 多路复用技术,在一个或少量线程中同时监控所有连接(包括监听套接字和已连接的客户端套接字)上的事件(如新连接到达、数据可读、可写等)。

Loop()方法:这是一个无限循环。在每次循环中,Reactor会阻塞在 epoll_wait这类调用上。一旦有任何被监控的连接上发生了它关心的事件(比如监听套接字上有新的连接请求,或某个客户端连接上有数据到达),epoll_wait就会返回。Reactor随后会根据事件的类型,通过哈希表找到对应的 Connection对象。如果是数据可读,就会多态调用Channel派生类中的Recver(),将内核缓冲区中的数据读取到用户接受缓冲区中,并触发其事先注册好的回调函数

我们来运行测试一下,由于我们只实现了服务器,并没有实现客户端,所以我们这里可以使用之前网络计算机的客户端来进行测试

运行结果

至此,我们实现了单 Reactor 单线程模型


7. 总结

在实践中,根据如何处理接收连接(Accept)和I/O读写(Read/Write)操作,Reactor模式演化出三种主要模型,其性能和处理能力依次提升。

  1. 单 Reactor 单线程模型
    • 描述:所有工作(接收新连接、I/O读写、业务处理)都在一个线程内完成。
    • 优点:模型简单,无线程切换和同步问题。
    • 缺点性能瓶颈明显。如果业务处理耗时,会阻塞整个事件循环,无法及时响应其他事件。
    • 适用场景:适用于业务处理非常快速的场景,如 Redis
  2. 单 Reactor 多线程模型
    • 描述:Reactor 线程仅负责监听事件、接收连接和I/O读写。当读到数据后,将业务处理任务提交给一个后台线程池处理,处理完成后再由 Reactor 线程发送结果。
    • 优点:将耗时的业务计算与 I/O 处理分离,能充分利用多核CPU,提高了吞吐量。
    • 缺点:Reactor 本身仍是单线程,在高并发下,所有I/O操作仍可能成为瓶颈。
  3. 主从 Reactor 多线程模型
    • 描述:这是功能与性能最完善的模型。
      • 主Reactor:由一个独立线程运行,只负责接收新的客户端连接。建立连接后,将其分配给子Reactor
      • 子Reactor:由一个线程池运行。每个子Reactor负责监听一组已建立连接的I/O事件(读/写),并进行数据读写。业务处理同样交给后台工作线程池。
    • 优点职责分明,模块间耦合度低。主Reactor快速响应新连接,子Reactor专注I/O,能支持极高的并发量
    • 适用场景高性能、高并发服务器的首选模型,如 Netty, Nginx

模式对比与优劣分析

了解不同模型后,我们再从宏观视角对比一下Reactor模式与其他传统模式的区别,以及其自身的优缺点。

特性传统多线程模式生产者-消费者模式Reactor 模式
线程模型一个连接一个线程多线程 + 任务队列单/多线程事件循环
资源消耗高(线程资源宝贵)中等(线程池可控)低(线程数少)
上下文切换频繁,开销大频繁,开销大极少
适用场景连接数少、长连接CPU密集型任务I/O密集型高并发
复杂度编程简单,但资源管理复杂线程同步复杂度高回调设计复杂(回调地狱)

基于以上对比,Reactor模式的优缺点可以总结为:

  • 优点
    • 高并发与可扩展性:能够用少量线程处理大量连接,资源利用率高。
    • 解耦与模块化:将事件分发与业务处理分离,结构清晰。
    • 响应性:避免了因单个I/O操作阻塞而影响其他请求的处理。
  • 缺点
    • 编程复杂度高:基于回调的异步编程模型容易导致代码支离破碎(回调地狱),不易调试。
    • 对CPU密集型任务不友好:如果在事件处理线程中执行耗时计算,会严重拖慢整个系统的响应速度。通常需要与线程池结合,将计算任务卸载。

总结

总而言之,Reactor模式通过事件驱动和I/O多路复用技术,巧妙地解决了高并发网络编程中的资源瓶颈问题。它特别适合构建需要处理成千上万个并发连接的I/O密集型系统,如Web服务器、即时通讯网关和微服务框架等。

虽然编程模型相对复杂,但其在性能和资源消耗上的巨大优势,使其成为现代高性能网络编程的基石之一。知名的网络框架如Netty、Muduo等,都是Reactor模式的优秀实践。

本文地址:https://www.yitenyun.com/2346.html

搜索文章

Tags

#飞书 #人工智能 #语言模型 #服务器 #大模型 #ai #ai大模型 #agent #python #pip #conda #AI #log4j #ollama #微信 #运维 #私有化部署 #学习 #产品经理 #AI大模型 #大模型学习 #大模型教程 #AI编程 #飞牛nas #fnos #github #信息与通信 #自然语言处理 #rpa #实时互动 #远程工作 #kylin #docker #arm #linux #云计算 #云原生 #ios面试 #ios弱网 #断点续传 #ios开发 #objective-c #ios #ios缓存 #ssh #Trae #IDE #AI 原生集成开发环境 #Trae AI #fastapi #html #css #mongodb #数据库 #算法 #数据结构 #PyTorch #深度学习 #模型训练 #星图GPU #银河麒麟高级服务器操作系统安装 #银河麒麟高级服务器V11配置 #设置基础软件仓库时出错 #银河麒高级服务器系统的实操教程 #生产级部署银河麒麟服务系统教程 #Linux系统的快速上手教程 #ARM服务器 # GLM-4.6V # 多模态推理 #vscode #ubuntu #gitee #kubernetes #笔记 #平面 #容器 #学习方法 香港站群服务器 多IP服务器 香港站群 站群服务器 #分布式 #架构 #配置中心 #SpringCloud #Apollo #大数据 #职场和发展 #程序员创富 #AIGC #开源 #mysql #分库分表 #垂直分库 #水平分表 #雪花算法 #分布式ID #跨库查询 #llama #opencv #神经网络 #自动化 #ansible #科技 #数学建模 #企业微信 #AI办公 #智能助手 #开发语言 #华为云 #部署上线 #动静分离 #Nginx #新人首发 #音视频 #YOLO #java #spring boot #maven #spring #ide #前端 #javascript #pytorch #notepad++ #大语言模型 #长文本处理 #GLM-4 #Triton推理 #web安全 #安全 #php #网络安全 #就业指南 #大模型入门 #网络 #tcp/ip #hadoop #hbase #hive #zookeeper #spark #kafka #flink #流程图 #论文阅读 #信息可视化 #Telegram机器人 #ClawdBot #多模态翻译 #大模型推理 #springboot #C++ #Reactor #低代码 #爬虫 #gemini #gemini国内访问 #gemini api #gemini中转搭建 #Cloudflare #golang #数据结构与算法 #node.js #rag #langchain #CFD #区块链 #测试用例 #生活 #pycharm #阿里云 #FRP #http #mcp #mcp server #AI实战 #物联网 #websocket #Agent #程序员 #sql #agi #MobaXterm #SSM 框架 #孕期健康 #产品服务推荐 #推荐系统 #用户交互 #机器学习 #windows #进程控制 #项目 #高并发 #java-ee #flutter #鸿蒙 #nginx #经验分享 #安卓 #微服务 #Oauth2 #aws #fabric #postgresql #openHiTLS #TLCP #DTLCP #密码学 #商用密码算法 #重构 #计算机视觉 #堡垒机 #安恒明御堡垒机 #windterm #harmonyos #华为 #矩阵 #线性代数 #AI运算 #向量 #FaceFusion # Token调度 # 显存优化 #word #umeditor粘贴word #ueditor粘贴word #ueditor复制word #ueditor上传word图片 #RTP over RTSP #RTP over TCP #RTSP服务器 #RTP #TCP发送RTP #多个客户端访问 #IO多路复用 #回显服务器 #TCP相关API #RAGFlow #DeepSeek-R1 #分阶段策略 #模型协议 #开源软件 #iventoy #VmWare #OpenEuler #能源 #Ansible # 自动化部署 # VibeThinker #Linux #TCP #c++ #线程 #线程池 #驱动开发 #git #HCIA-Datacom #H12-811 #题库 #最新题库 #鸿蒙PC #后端 #MCP #MCP服务器 #腾讯云 #ddos #visual studio #测试工具 #https #网络协议 #centos #Windows 更新 #风控模型 #决策盲区 #android #c# #转行 #RAG #RAG调优 #RAG系统 #召回 #qt #FL Studio #FLStudio #FL Studio2025 #FL Studio2026 #FL Studio25 #FL Studio26 #水果软件 #unity #游戏引擎 #正则 #正则表达式 #电脑 #mvp #个人开发 #设计模式 #性能优化 #vue上传解决方案 #vue断点续传 #vue分片上传下载 #vue分块上传下载 #dify #pjsip #ci/cd #jenkins #gitlab #数信院生信服务器 #Rstudio #生信入门 #生信云服务器 #毕业设计 #mobaxterm #程序人生 #科研 #博士 #课程设计 #cpolar #stm32 #Conda # 私有索引 # 包管理 #ai agent #ai大小模型 #小模型 #开源小模型 #8b模型 #国产大模型 #SOTA #进程 #vue.js #论文 #毕设 #缓存 #redis #Harbor #ecmascript #elementui #le audio #蓝牙 #低功耗音频 #通信 #连接 #serverless #硬件工程 #rocketmq #iBMC #UltraISO #知识图谱 #servlet #microsoft #bytebase #PyCharm # 远程调试 # YOLOFuse #jar #内网穿透 #swiftui #swift #内存治理 #django #scrapy #jvm #学习笔记 #jdk #单片机 #嵌入式硬件 #电脑故障 #文件系统 #搜索引擎 #导航网 #超算服务器 #算力 #高性能计算 #仿真分析工作站 #文心一言 #AI智能体 #牛客周赛 #spring cloud #json #lvs #负载均衡 #mcu #处理器模块 #现货库存 #价格优惠 #PM864AK01 #3BSE018161R1 #PLC #控制器模块 #散列表 #哈希算法 #企业开发 #ERP #项目实践 #.NET开发 #C#编程 #编程与数学 #Canal #udp #c语言 #ui #团队开发 #墨刀 #figma #DeepSeek #服务器繁忙 #matlab #支持向量机 #lstm #分类 #jetty #jmeter #功能测试 #软件测试 #自动化测试 #Redisson #华为od #华为od机考真题 #华为od机试真题 #华为OD上机考试真题 #华为OD机试双机位C卷 #华为OD上机考试双机位C卷 #华为ODFLASH坏块监测系统 #链表 #时序数据库 #儿童书籍 #儿童诗歌 #童话故事 #经典好书 #儿童文学 #好书推荐 #经典文学作品 #svn #vim #gcc #yum #uni-app #小程序 #蓝桥杯 #设备驱动 #芯片资料 #网卡 #ESXi #gitea #ESP32 #开发环境搭建 #ssl #OCR #文档识别 #DeepSeek-OCR-2 #信创适配 #360AI图片精简版 #看图工具 #电脑看图工具 #360看图工具 #AI看图工具 #select #vllm #机器人 #面试 #内容运营 #产品运营 #推荐算法 #ProCAST2025 #ProCast #脱模 #顶出 #应力计算 #铸造仿真 #变形计算 #FTP服务器 #游戏 #shell #CPU利用率 #dubbo #压枪 #2026年美赛C题代码 #2026年美赛 #计算机网络 #java大文件上传 #java大文件秒传 #java大文件上传下载 #java文件传输解决方案 #服务器架构 #AI推理芯片 #es安装 #leetcode #prometheus #diskinfo # TensorFlow # 磁盘健康 #高仿永硕E盘的个人网盘系统源码 #web #webdav #新浪微博 #前端框架 #边缘计算 #LangFlow #智能体 #autosar #CISSP #CISSP考点 #信息安全 #CISSP哪里考 #公众号:厦门微思网络 #+微信号:xmweisi #开源社区 #国产基础软件 #操作系统 #AI框架 #Rust #LLM #css3 #线性回归 #嵌入式 #鸭科夫 #逃离鸭科夫 #鸭科夫联机 #鸭科夫异地联机 #开服 #防排烟监控 #消防风机一体化 #BA楼宇自控 #DDC控制器 #IBMS集成系统 #numpy #scikit-learn #matplotlib #FutureWarning #汽车 #SSH # ProxyJump # 跳板机 #目标检测 #pyqt #单目测距 #速度估计 #pyqt界面 #注意力机制 #国企混改 #国企混改咨询 #国企混改战略规划 #GPU #曦望 #自动化巡检 #APM #AudioPolicy #音频策略 #Dell #PowerEdge620 #内存 #硬盘 #RAID5 #pdf #excel #LabVIEW #光谱仪 #串口通信 #AQ6370 #chrome #go #unitask #系统架构 #xss #selenium #远程连接 #三种参数 #参数的校验 #fastAPI #我的世界 #游戏私服 #云服务器 #系统安全 #AI写作 #数列 #数学 #数论 #洛谷 #openclaw #实在Agent #PowerBI #企业 #全能视频处理软件 #视频裁剪工具 #视频合并工具 #视频压缩工具 #视频字幕提取 #视频处理工具 #压力测试 #数据挖掘 #架构师 #软考 #系统架构师 #程序设计 #计算机毕业设计 #程序定制 #源码 #大作业 #社科数据 #数据分析 #数据统计 #经管数据 #Ubuntu服务器 #硬盘扩容 #命令行操作 #VMware #职场发展 #深度优先 #DFS #创业创新 #论文笔记 #wpf #策略模式 #SSE #whisper #软件工程 #虚幻 #ue5 #transformer #微信小程序 #计算机 #连锁药店 #连锁店 #flask #Buck #NVIDIA #交错并联 #DGX #同步WebServer服务器 #ESP32网页服务器 #轻量级http服务器 #ESP32物联网 #chatgpt #ffmpeg #酒店客房管理系统 #DS随心转 #google #search #钉钉 #visual studio code #postman #easyui #sqlmap #单元测试 #零售 #TRO #TRO侵权 #TRO和解 #macos #数字化转型 #实体经济 #中小企业 #商业模式 #软件开发 #青蓝送水模式 #创业干货 #3d #健康医疗 #金融 #教育电商 #媒体 #prompt #广播 #组播 #并发服务器 #防毒口罩 #防尘口罩 #具身智能 #发展心理学 #运动控制 #内在动机 #镜像神经元 #交叉学科 #企业架构治理 #电力企业IT架构 #IT架构设计 #arm开发 #思维模型 #认知框架 #认知 #无人机 #安全架构 #数字营销 #seo #stl #数据仓库 #ISP Pipeline #行缓冲 #react.js #laravel #游戏美术 #技术美术 #游戏策划 #游戏程序 #用户体验 #wsl #L2C #勒让德到切比雪夫 #逻辑回归 #Android #Bluedroid #大模型面试 #openresty #lua #mybatis #后端 #math #homework #rpc #protobuf #googlecloud #SEO #七年级上册数学 #有理数 #有理数的加法法则 #绝对值 #肿瘤相关巨噬细胞 #CXCL5 #信号通路 #胃癌 #mTOR #乐备实 #labex #wps #敏捷流程 #AI大模型应用开发 #语义检索 #文本向量化 #GTE-Pro #企业AI #Modbus-TCP #电商 # Triton # 高并发 #DisM++ # 系统维护 #powerpoint #Com #计算机现代史 #本地部署 #vLLM #IPMI #模型微调 #智慧校园一体化平台 #智慧校园管理系统 #合肥自友科技-智慧校园 #智慧校园源头厂家 #智慧校园软件供应商 #智慧校园平台服务商 #高性价比智慧校园系统 #MIMO #OFDM #技术原理 #通信算法 #阻塞队列 #生产者消费者模型 #服务器崩坏原因 #GNC #控制 #姿轨控 #测试覆盖率 #可用性测试 #智能体从0到1 #新手入门 #bash #车辆排放 #dreamweaver #信号处理 #目标跟踪 #OBC #Playbook #AI服务器 #labview #集成测试 #oracle #AI产品经理 #大模型开发 #打卡 #计算机英语翻译 #海外服务器安装宝塔面板 #sglang #mmap #nio #Java面试 #Java程序员 #后端开发 #Redis #分布式锁 #爱心代码 #表白代码 #爱心 #tkinter #情人节表白代码 #测评 #SQL #编辑器 #tcp/ip #智能路由器 #osg #echarts #MapGIS #云服务 #云门户 #IGServer #YOLO26 #YOLO11 #设计规范 #放大电路 #abtest #LangGraph #r-tree #漏洞 #数据安全 #注入漏洞 #typescript #list #智能路由器 #自动驾驶 #fastmcp #tomcat #RAID #磁盘 #系统管理 #服务 #pipeline #Transformers #NLP #AI运维 #Clawdbot #企业微信集成 #DevOps自动化 #全栈 #智能家居 #sqlserver #蓝耘智算 #ZeroTermux #宝塔面板 #移动服务器 #Linux环境 #gpu算力 #状态模式 #android-studio #android studio #android runtime #多线程 #数组 #性能调优策略 #双锁实现细节 #动态分配节点内存 #vue3 #天地图 #403 Forbidden #天地图403错误 #服务器403问题 #天地图API #部署报错 #IndexTTS2 # 阿里云安骑士 # 木马查杀 #银河麒麟 #人大金仓 #Kingbase #GB/T4857 #GB/T4857.17 #GB/T4857测试 #企业级存储 #网络设备 #cnn #SAM3 #麒麟 #国产化 #clawdbot #QQbot #QQ #SSH保活 #Miniconda #远程开发 #everything #材料工程 #数码相机 #智能电视 #rust #twitter #svm #amdgpu #kfd #ROCm #esp32 arduino #Java #Spring #Spring Boot #react native #KMS 激活 #eureka #sql注入 #b/s架构 #ssm #移动学习平台 #企业存储 #RustFS #对象存储 #高可用 #JavaScript #结构体 #Deepseek #gpt-3 #软件构建 #迁移重构 #代码迁移 #DHCP #百度 #百度文库 #爱企查 #旋转验证码 #验证码识别 #图像识别 #adb #聚类 #CNAS #CMA #程序文件 #firefox #STL #string #笔试 #windbg分析蓝屏教程 #vnstat #监控 ##程序员和算法的浪漫 #WT-2026-0001 #QVD-2026-4572 #smartermail #语义搜索 #嵌入模型 #Qwen3 #AI推理 #源代码管理 #js逆向 #逆向 #混淆 #ai编程 #运营 #京东云 #命令模式 #阳台种菜 #园艺手扎 #Gemini #Nano Banana Pro #elasticsearch #版本控制 #Git入门 #开发工具 #代码托管 #研发管理 #禅道 #禅道云端部署 #计算几何 #斜率 #方向归一化 #叉积 #其他 #SEO优化 #微PE #硬盘克隆 #DiskGenius #Moltbot #.net #算法备案 #CCE #Dify-LLM #Flexus #漏洞挖掘 #Exchange #spine #扩展屏应用开发 #vue #asp.net #私域运营 #流量运营 #risc-v #安全威胁分析 #window10 #window11 #病毒 #DCOM进程 #系统进程资源占用高 #bootstrap #中间件 #考研 #可信计算技术 #Smokeping #Moltbook #Cpolar #国庆假期 #服务器告警 #智能手机 #SSH代理转发 #图像分类 #图像分割 #yolo26算法 #求职招聘 #copilot #数据采集 #汇编 #epoll #tensorflow #KMP #企业微信机器人 #本地大模型 #AI聊天机器人 #隐私合规 #网络安全保险 #法律风险 #风险管理 # IndexTTS 2.0 # 自动化运维 #intellij-idea #database #idea #儿童AI #图像生成 #Qwen #容斥原理 #wordpress #雨云 #单例模式 #娱乐 #.netcore #部署 #apache #n8n解惑 #社交智慧 #职场生存 #系统思维 #身体管理 #商务宴请 #拒绝油腻 #清醒日常 #SSH Agent Forwarding # PyTorch # 容器化 #openvino #手机检测 #课堂手机检测 #语音识别 #统信UOS #搜狗输入法 #WIN32汇编 #文本生成 #AI助手 #windows11 #系统修复 #homelab #Lattepanda #Jellyfin #Plex #Emby #Kodi #todesk #幼儿园 #园长 #幼教 #余行补位 #意义对谈 #余行论 #领导者定义计划 #就业 #http头信息 #rabbitmq #Keycloak #Quarkus #AI编程需求分析 #带宽 #流量 #大带宽 #鸿蒙系统 #车载系统 #junit #Kylin-Server #国产操作系统 #服务器安装 #若依 #quartz #框架 # CUDA #clickhouse #用户运营 #Ubuntu #Steam #饥荒联机版 #iphone #CPU #监测 #ShaderGraph #图形 #Taiji #Fun-ASR # 语音识别 # WebUI #claude #LoRA # RTX 3090 # lora-scripts #CUDA #Triton #nmodbus4类库使用教程 #高品质会员管理系统 #收银系统 #同城配送 #最好用的电商系统 #最好用的系统 #推荐的前十系统 #JAVA PHP 小程序 #jupyter #Streamlit #TURN # WebRTC # HiChatBox #文字检测 #梁辰兴 #传输连接管理 #计算机网络基础 #运维开发 #gpio #Chat平台 #ARM架构 #azure #cocoa #Tetrazine-Acid #1380500-92-4 #贪心算法 #SIP服务器 #语音服务器 #VoIP #SIP协议 #AI-native #dba #测试流程 #金融项目实战 #P2P #html5 #反向代理 #webrtc #Springboot3.0 #守护进程 #复用 #screen #门禁 #读卡器 #梯控 #门禁一卡通 #门禁读卡器 #梯控读卡器 #IC卡读卡器 #启发式算法 #winscp #智能化测试 #质量效能 #skills #playwright #持续测试 #职业和发展 #未加引号服务路径 #超算中心 #PBS #lsf # 双因素认证 #fpga开发 #2026AI元年 #年度趋势 #跳槽 #业界资讯 #Docker #投标 #标书制作 #网络攻击模型 #制造 #ipmitool #BMC #mvc #asp.net大文件上传 #asp.net大文件上传下载 #asp.net大文件上传源码 #ASP.NET断点续传 #排序算法 #插入排序 #收银台开源 #收银台接口 #东方仙盟 #仙盟创梦IDE #商业开源 #bond #服务器链路聚合 #网卡绑定 #交互 #2026美国大学生数学建模 #2026美赛 #美赛ICM #美赛ICM Problem F #ICM赛题F #MATLAB #omv8 #树莓派 #nas #春秋云境 #CVE-2020-5515 #高考 #6G #太赫兹 #无线通信 #频谱 #无线 #数据集 #并发 #KMS激活 #uv #铬锐特 #uv胶 #紫外线胶水 #光固化胶水 #胶粘剂 #CSDN #动态规划 #全链路优化 #实战教程 #vision pro #旅游推荐管理系统 #旅游攻略 #电气工程 #C# # GLM-4.6V-Flash-WEB # AI部署 #AB包 #AI生成 # outputs目录 # 自动化 #embedding #AutoDL使用教程 #AI大模型训练 #linux常用命令 #PaddleOCR训练 #建站 #Tracker 服务器 #响应最快 #torrent 下载 #2026年 #Aria2 可用 #迅雷可用 #BT工具通用 #在线培训系统 #m3u8 #HLS #移动端H5网页 #APP安卓苹果ios #监控画面 直播视频流 #DooTask #RPA #影刀RPA #vuejs #Puppet # IndexTTS2 # TTS #非标机械设计 # 显卡驱动备份 #grafana #xeon #cursor #uvicorn #uvloop #asgi #event #聊天小程序 #gpt #TensorRT # 推理优化 #数模美赛 #三维 #3D #三维重建 #信令服务器 #Janus #MediaSoup #CVE-2025-61686 #路径遍历高危漏洞 #Llama-Factory # 大模型推理 #毕设代做 #课设 #Jetty # CosyVoice3 # 嵌入式服务器 #HeyGem # 服务器IP # 端口7860 #建筑缺陷 #红外 #需求分析 # GPU租赁 # 自建服务器 #戴尔服务器 #戴尔730 #装系统 #usb #通信协议 #ocr #lprnet #车牌识别 #crnn #车牌检测 #代理 #5G #平板 #交通物流 #智能硬件 #图书馆 #自习室 #提词器 #芦笋提词器 #遛狗 #MinIO服务器启动与配置详解 #智能体来了 #SSH复用 # Miniconda # 远程开发 #Claude #视频去字幕 #IO #机器视觉 #6D位姿 #mssql #GATT服务器 #蓝牙低功耗 #n8n #nodejs #esb接口 #走处理类报异常 #bug菌问答团队 #AI电商客服 #昇腾300I DUO #银河麒麟部署 #银河麒麟部署文档 #银河麒麟linux #银河麒麟linux部署教程 #以太网温湿度气体多参量传感器 #以太网多合一传感器 #以太网环境监测终端 #可定制气体监测模组 #双指针 #考试系统 #在线考试 #培训考试 #考试练习 # 远程连接 #memcache #vp9 #LED #设备树 #GPIO #gerrit #轻量大模型 #指针 #anaconda #虚拟环境 #GB28181 #SIP信令 #SpringBoot #视频监控 #ModelEngine #银河麒麟操作系统 #openssh #华为交换机 #信创终端 #流媒体 #NAS #飞牛NAS #NVR #EasyNVR #系统升级 #信创 #mariadb #编程助手 #Gunicorn #WSGI #Flask #并发模型 #容器化 #Python #性能调优 #sentinel #长文本理解 #glm-4 #推理部署 #proc #ambari #I/O #Lenyiin #ceph #muduo库 #1024程序员节 #RustDesk # IndexTTS # GPU集群 #国产化OS #SSH跳转 #GPU服务器 #weston #x11 #x11显示服务器 #一人公司 #独立开发者 #RSO #机器人操作系统 #sqlite #直流无刷电机 #六步换相 #vivado license #cpu #CVE-2025-68143 #CVE-2025-68144 #CVE-2025-68145 #ONLYOFFICE #MCP 服务器 #大模型呼叫 #外呼系统 #AI外呼 #外呼系统推荐 #智能客服 #外呼 # 数字人系统 # 远程部署 #muduo #EventLoop #连接数据库报错 #GitPuk #国产开源免费代码管理工具 #Arbess #cicd工具 #一文上手 # 黑屏模式 # TTS服务器 #kong #Kong Audio #Kong Audio3 #KongAudio3 #空音3 #空音 #中国民乐 #IndexTTS 2.0 #本地化部署 #AI论文写作工具 #学术论文创作 #论文效率提升 #MBA论文写作 #ajax #编程语言 #旅游 #生信 #OpenAI #故障 #优化 #paddleocr #大模型应用 #API调用 #PyInstaller打包运行 #服务端部署 #pencil #pencil.dev #设计 #Ascend #MindIE #静脉曲张 #腿部健康 #spring native #公共MQTT服务器 #Tokio #异步编程 #系统编程 #Pin #http服务器 #mybatis #HistoryServer #Spark #YARN #jobhistory #防火墙 #UEFI #BIOS #Legacy BIOS #内存接口 # 澜起科技 # 服务器主板 #算法笔记 #简单数论 #埃氏筛法 #codex #Zernike #hcipy #光学设计 #像差仿真 #SEW #赛威 #SEW变频器 #高级IO #yolov12 #研究生life #gpu #nvcc #cuda #nvidia #mapreduce #里氏替换原则 #zabbix #汇智网盘系统 #企业级云存储 #智能协作 #科普 #JT/T808 #车联网 #车载终端 #模拟器 #仿真器 #开发测试 #GESP4级 #GESP四级 #sort #滑动窗口 #字符串 #智慧社区 #管理系统 #RXT4090显卡 #RTX4090 #深度学习服务器 #硬件选型 #AI赋能盾构隧道巡检 #开启基建安全新篇章 #以注意力为核心 #YOLOv12 #AI隧道盾构场景 #盾构管壁缺陷病害异常检测预警 #隧道病害缺陷检测 #IntelliJ IDEA #模块 #openEuler #scala #卷积神经网络 #IT #技术 #sizeof和strlen区别 #sizeof #strlen #计算数据类型字节数 #计算字符串长度 #健身房预约系统 #健身房管理系统 #健身管理系统 #ThingsBoard MCP # 公钥认证 #LabVIEW知识 #LabVIEW程序 #LabVIEW功能 #改行学it #rustdesk # 服务器IP访问 # 端口映射 #debian #标准化事件委托 #工序流程工艺路径 #业务流程标准化 #api #key #AI作画 #clamav #榛樿鍒嗙被 #CANN #文生视频 #CogVideoX #AI部署 #TCP服务器 #语音控制 #图像处理 #yolo #硬件 #全排列 #回溯 #剪枝 #STJ算法 #密码 #行为模式分析 #数据 #应用层 #跨领域 #敏感信息 #RTSP #Live555 #流媒体服务器 #8U #硬件架构 #强化学习 #策略梯度 #REINFORCE #蒙特卡洛 #docker-compose #fiddler #ROS # 局域网访问 # 批量处理 #算力一体机 #ai算力服务器 #synchronized #锁 #reentrantlock # 树莓派 # ARM架构 #opc ua #opc #LVDS #高速ADC #DDR # GLM-TTS # 数据安全 #xshell #host key #TTS私有化 # 音色克隆 # OTA升级 # 黄山派 #JAVA #C₃₂H₄₅N₇O₁₁S₂ #支付 #分布式数据库 #集中式数据库 #业务需求 #选型误 #几何学 #拓扑学 #ip #Cesium #交互设计 #智能避障 #blender #设计师 #学工管理系统 #学工一体化平台 #学工软件二次开发 #学工平台定制开发 #学工系统服务商 #学工系统源头厂家 #智慧校园学工系统 #智能一卡通 #消费一卡通 #智能梯控 #一卡通 #超时设置 #客户端/服务器 #网络编程 #1panel #vmware #python学习路线 #python基础 #python进阶 #python标准库 #seata #TC/TM/RM #kmeans #TcpServer #accept #高并发服务器 #金融投资Agent #x-cmd #doubao #kimi #zhipu #claude-code #摩尔线程 #uniapp #合法域名校验出错 #服务器域名配置不生效 #request域名配置 #已经配置好了但还是报错 #uniapp微信小程序 #ICPC #ida #glibc #paddlepaddle #Anaconda配置云虚拟环境 #MQTT协议 #政务 #r语言-4.2.1 #r语言 #语言 #参数估计 #矩估计 #概率论 #STUN # TURN # NAT穿透 #泛型 #接口 #抽象类 #面向对象设计 #LE Audio #BAP #ueditor导入word #ueditor导入pdf #RAID技术 #存储 #dash #捷配 #pcb工艺 #区间dp #二进制枚举 #图论 #可再生能源 #绿色算力 #风电 #markdown #智能制造 #供应链管理 #工业工程 #时间复杂度 #空间复杂度 #eclipse #域名注册 #新媒体运营 #网站建设 #国外域名 #HBA卡 #RAID卡 #前端界面 #Discord机器人 #云部署 #程序那些事 #Coze工作流 #AI Agent指挥官 #多智能体系统 #回归 #llm #领域驱动 #Spring AI #AI Agent #开发者工具 #pytest #IO编程 #web3.py #串口服务器 #工业级串口服务器 #串口转以太网 #串口设备联网通讯模块 #串口服务器选型 #计算机外设 #树莓派4b安装系统 #智慧城市 #comfyui #模板和元编程 #zygote #应用进程 #pve #多进程 #python技巧 #我的世界服务器搭建 #minecraft #zotero #WebDAV #同步失败 #代理模式 #claude code #code cli #ccusage #V11 #kylinos #PyTorch 特性 #动态计算图 #张量(Tensor) #自动求导Autograd #GPU 加速 #生态系统与社区支持 #与其他框架的对比 #Node.js #漏洞检测 #CVE-2025-27210 #SSH免密登录 #journalctl #React #Next #CVE-2025-55182 #RSC #学术写作辅助 #论文创作效率提升 #AI写论文实测 #LobeChat #GPU加速 #远程访问 #远程办公 #飞网 #安全高效 #配置简单 #快递盒检测检测系统 #p2p #YOLOFuse # 水冷服务器 # 风冷服务器 #910B #笔记本电脑 #hibernate #逆向工程 #GEO服务 #ngrok #翻译 #开源工具 #ZooKeeper #ZooKeeper面试题 #面试宝典 #深入解析 #水性三防漆 #UV三防漆 #有机硅三防漆 #聚氨酯三防漆 #醇酸树脂三防漆 #丙烯酸三防漆 #防毒面罩 #防尘面罩 #openlayers #bmap #tile #server #web3 #elk #黑客技术 #挖漏洞 #日志分析 #决策树 #网络配置实战 #Web/FTP 服务访问 #计算机网络实验 #外网访问内网服务器 #Cisco 路由器配置 #静态端口映射 #网络运维 #galeweather.cn #高精度天气预报数据 #光伏功率预测 #风电功率预测 #高精度气象 #CosyVoice3 # 语音合成 #OSS #CDN #最佳实践 #eBPF #SSH反向隧道 # Jupyter远程访问 #Socket #模拟退火算法 #集成学习 #虚拟机 #EMC存储 #存储维护 #NetApp存储 #Hadoop #客户端 #DIY机器人工房 #nacos #银河麒麟aarch64 #实时音视频 #UDP套接字编程 #UDP协议 #网络测试 #文件传输 #电脑文件传输 #电脑传输文件 #电脑怎么传输文件到另一台电脑 #电脑传输文件到另一台电脑 #论文复现 #unix #asp.net上传文件夹 #SSH别名 #知识 #鼠大侠网络验证系统源码 #群晖 #音乐 #neo4j #NoSQL #Java生成PDF #Freemarker转PDF #PDFBox转图片 #HTML转PDF乱码解决 #AI技术 #ping通服务器 #读不了内网数据库 #AutoDL ##租显卡 #空间计算 #原型模式 #VibeVoice # 云服务器 #Kuikly #openharmony #Android16 #音频性能实战 #音频进阶 #reactor反应堆 #数据访问 #H5网页 #网页白屏 #H5页面空白 #资源加载问题 #打包部署后网页打不开 #HBuilderX #电路仿真 #proteus #AD #keil #硬件工程师面试 #EDCA OS #可控AI #arm64 #Deepoc #具身模型 #开发板 #未来 #自动化运维 #flume #UOS #海光K100 #统信 #零代码平台 #AI开发 #UDP #实时检测 #tdengine #涛思数据 #Modbus #MOXA #ms-swift # 一锤定音 # 大模型微调 #deepseek #环境搭建 #SSH公钥认证 # 安全加固 #练习 #基础练习 #循环 #九九乘法表 #计算机实现 #pandas #Proxmox VE #虚拟化 #esp32教程 #cpp #ipv6 #数据可视化 #网路编程 #百万并发 #NPU #rtmp #动画 #c++20 #流量监控 #Qwen3-14B # 大模型部署 # 私有化AI #测试网 #erc-20 #独立链 #polkadot #IFix #408 #线索二叉树 # 环境迁移 #邮箱 #postfix #dovecot #攻防演练 #Java web #红队 #SMP(软件制作平台) #EOM(企业经营模型) #应用系统 #H5 #跨域 #发布上线后跨域报错 #请求接口跨域问题解决 #跨域请求代理配置 #request浏览器跨域 #screen 命令 #游戏机 #JumpServer #建造者模式 #知识库 #UDP的API使用 #黑群晖 #无U盘 #纯小白 #ue4 #DedicatedServer #独立服务器 #专用服务器 #MC #screen命令 #链表的销毁 #链表的排序 #链表倒置 #判断链表是否有环 #AirDrop #振镜 #振镜焊接 #蓝湖 #Axure原型发布 #claudeCode #content7 #挖矿 #Linux病毒 # 目标检测 #chat #多接口并发 #首页优化 #SAP #ebs #metaerp #oracle ebs #React安全 #漏洞分析 #Next.js #反序列化漏洞 #vlookup # 串口服务器 # NPort5630 #人脸识别 #人脸核身 #活体检测 #身份认证与人脸对比 #微信公众号 #Highcharts #插件封装 #框架搭建 #SRS #直播 #灌封胶 #有机硅灌封胶 #聚氨酯灌封胶 #环氧树脂灌封胶 #电子灌封胶 #华为机试 #OpenHarmony #milvus #Python办公自动化 #Python办公 #昇腾 #TTS #C语言 #标准IO #函数接口 #小白 #模型上下文协议 #MultiServerMCPC #load_mcp_tools #load_mcp_prompt # 批量管理 #智慧校园解决方案 #智慧校园选型 #智慧校园采购 #智慧校园软件 #智慧校园专项资金 #智慧校园定制开发 #证书 #VMware Workstation16 #服务器操作系统 #后端框架 #ArkUI #ArkTS #鸿蒙开发 #CPU推理 #Nacos #创业管理 #财务管理 #团队协作 #创始人必修课 #数字化决策 #经营管理 #贝叶斯优化深度学习 #MCP服务器注解 #异步支持 #方法筛选 #声明式编程 #自动筛选机制 # 远程访问 # 服务器IP配置 #系统安装 #进程创建与终止 #xlwings #Excel #dlms #dlms协议 #逻辑设备 #逻辑设置间权限 #wireshark #unity3d #服务器框架 #Fantasy #运动 #VS Code调试配置 #K8s #镜像 #集群自动化 #题解 #图 #dijkstra #迪杰斯特拉 #tcpdump #HTML #web前端 #网页开发 #文件IO #输入输出流 #麒麟OS #文件管理 #文件服务器 #powerbi #SQL调优 #EXPLAIN #慢查询日志 #分布式架构 #工厂模式 #scanf #printf #getchar #putchar #cin #cout #mamba #海外短剧 #海外短剧app开发 #海外短剧系统开发 #短剧APP #短剧APP开发 #短剧系统开发 #海外短剧项目 #凤希AI伴侣 #iot #连锁门店核销 #美团团购券核销 #美团核销api #saas平台美团核销 #java接入美团团购 #STDIO协议 #Streamable-HTTP #McpTool注解 #服务器能力 #租显卡 #训练推理 #AI应用 #can #Dify #轻量化 #低配服务器 #Anything-LLM #IDC服务器 #工具集 #江协 #瑞萨 #OLED屏幕移植 #hdfs #Spring源码 #欧拉 #simulink #经济学 #docker安装seata #aiohttp #asyncio #异步 #软件 #本地生活 #电商系统 #商城 #VoxCPM-1.5-TTS # 云端GPU # PyCharm宕机 #webpack #梯控一卡通 #电梯一卡通 #考勤一卡通 #生产服务器问题查询 #日志过滤 #Autodl私有云 #深度服务器配置 #RK3576 #瑞芯微 #硬件设计 #rdp #浏览器指纹 #人脸识别sdk #视频编解码 #高精度农业气象 #漏洞修复 #IIS Crypto #大模型部署 #mindie #ComfyUI # 推理服务器 #懒汉式 #恶汉式 #gRPC #注册中心 #win11 #libosinfo #edge #迭代器模式 #观察者模式 #一周会议与活动 #ICLR #CCF #二值化 #Canny边缘检测 #轮廓检测 #透视变换 ##python学习笔记 #python中with语句详解 #架构设计 #联机教程 #局域网联机 #局域网联机教程 #局域网游戏 #路由器 #性能 #RAM #BIOS中断 #x86_64 #数字人系统 # 服务器迁移 # 回滚方案 #贴图 #材质 #身体实验室 #健康认知重构 #微行动 #NEAT效应 #亚健康自救 #ICT人 #asp.net上传大文件 #智能合约 #agentic bi #rtsp #转发 #CS2 #debian13 #turn #ICE #音乐分类 #音频分析 #ViT模型 #Gradio应用 #信创国产化 #达梦数据库 #鲲鹏 #Coturn #大学生 #温湿度监控 #WhatsApp通知 #IoT #MySQL #测速 #iperf #iperf3 #学术生涯规划 #CCF目录 #基金申请 #职称评定 #论文发表 #科研评价 #顶会顶刊 #SMARC #ARM # 代理转发 #idm #网站 #截图工具 #批量处理图片 #图片格式转换 #图片裁剪 #cocos2d #图形渲染 # 智能运维 # 性能瓶颈分析 #devops #SMTP # 内容安全 # Qwen3Guard #web服务器 #ARM64 # DDColor # ComfyUI #X11转发 #可撤销IBE #服务器辅助 #私钥更新 #安全性证明 #双线性Diffie-Hellman #短剧 #短剧小程序 #短剧系统 #微剧 #Fluentd #Sonic #日志采集 #面向对象 #安全性测试 #gateway #Comate # AI翻译机 # 实时翻译 #I/O模型 #水平触发、边缘触发 #多路复用 #期刊 #SCI #心理健康服务平台 #心理健康系统 #心理服务平台 #心理健康小程序 #北京百思可瑞教育 #百思可瑞教育 #北京百思教育 #restful #js #插件 #C++ UA Server #SDK #Windows #跨平台开发 #外卖配送 #全文检索 #FHSS #sklearn # ControlMaster #dynadot #域名 #程序员转型 #HarmonyOS APP #gnu #safari #模版 #函数 #类 #b树 #spring ai #oauth2 #memory mcp #Cursor #WEB #格式工厂 #千问 #寄存器 #大剑师 #nodejs面试题 #C2000 #TI #实时控制MCU #AI服务器电源 #vrrp #脑裂 #keepalived主备 #高可用主备都持有VIP #软件需求 #远程桌面 #远程控制 #SSH跳板机 # Python3.11 #API限流 # 频率限制 # 令牌桶算法 #项目申报系统 #项目申报管理 #项目申报 #企业项目申报 #内网 #视频 #rsync # 数据同步 #Aluminium #Google #工作 #渗透测试 #网安应急响应 #管道Pipe #system V #Shiro #CVE-2016-4437 #雨云服务器 #Minecraft服务器 #教程 #MCSM面板 #Apple AI #Apple 人工智能 #FoundationModel #Summarize #SwiftUI #uvx #uv pip #npx #Ruff # 服务器配置 # GPU #Gateway #认证服务器集成详解 #服务器开启 TLS v1.2 #IISCrypto 使用教程 #TLS 协议配置 #IIS 安全设置 #服务器运维工具 #YOLO识别 #YOLO环境搭建Windows #YOLO环境搭建Ubuntu #视觉检测 #WinSCP 下载安装教程 #SFTP #FTP工具 #服务器文件传输 #webgl #个人博客 # 键鼠锁定 #mtgsig #美团医药 #美团医药mtgsig #美团医药mtgsig1.2 #npm #VPS #搭建 #套接字 #I/O多路复用 #字节序 #工程设计 #预混 #扩散 #燃烧知识 #层流 #湍流 #土地承包延包 #领码SPARK #aPaaS+iPaaS #智能审核 #档案数字化 #Cubase #Cubase15 #Cubase14 #Cubase12 #Cubase13 #Cubase 15 Pro #Cubase 14 Pro #手机h5网页浏览器 #安卓app #苹果ios APP #手机电脑开启摄像头并排查 #MS #Materials #顶刊 #绘图 #研究生 #数据迁移 #国产PLM #瑞华丽PLM #瑞华丽 #PLM #嵌入式编译 #ccache #distcc #JNI #runtmie #express #cherry studio #puppeteer #KMS #slmgr #pygame #OWASP #juice-shop #安全漏洞练习靶场 #运维工具 #GLM-4.6V-Flash-WEB # AI视觉 # 本地部署 # Base64编码 # 多模态检测 #DDD #tdd #DNS #服务器IO模型 #非阻塞轮询模型 #多任务并发模型 #异步信号模型 #多路复用模型 # GPU服务器 # tmux #C #移动端h5网页 #调用浏览器摄像头并拍照 #开启摄像头权限 #拍照后查看与上传服务器端 #摄像头黑屏打不开问题 #nfs #iscsi #SPA #单页应用 # 远程运维 #swagger #性能测试 #LoadRunner #入侵 #日志排查 #Karalon #AI Test #TFTP #YOLOv8 # Docker镜像 #SA-PEKS # 关键词猜测攻击 # 盲签名 # 限速机制 # 大模型 # 模型训练 #Spring AOP #N8N #ET模式 #非阻塞 #remote-ssh #log #EtherCAT #XMC4800 #工业自动化 #工程实践 #晶振 #WinDbg #Windows调试 #内存转储分析 #CLI #langgraph.json #CMake #Make #C/C++ #西门子 #汇川 #Blazor #vps #浏览器自动化 #python #raid #raid阵列 #cascadeur #OpenManage #排序 #夏天云 #夏天云数据 #bigtop #hdp #hue #kerberos # 高并发部署 #Langchain-Chatchat # 国产化服务器 # 信创 #Python3.11 #reactjs #上下文工程 #langgraph #意图识别 #传统行业 #AI赋能 #Syslog #系统日志 #日志监控 #win10 #qemu #数智红包 #商业变革 #HarmonyOS #vertx #vert.x #vertx4 #runOnContext #攻击溯源 #编程 #warp #传感器 #MicroPython #WRF #WRFDA #机器人学习 #Go并发 #高并发架构 #Goroutine #系统设计 #net core #kestrel #web-server #asp.net-core # IP配置 # 0.0.0.0 #Zabbix #语音合成 #FASTMCP #英语学习 #交换机 #三层交换机 #高斯溅射 #istio #服务发现 #视觉理解 #Moondream2 #多模态AI #主板 #电源 #AI智能棋盘 #Rock Pi S #青少年编程 #MC群组服务器 #AI工具 #开关电源 #热敏电阻 #PTC热敏电阻 #说话人验证 #声纹识别 #CAM++ #勒索病毒 #勒索软件 #加密算法 #.bixi勒索病毒 #数据加密 #云开发 #OPCUA #CA证书 #星际航行 #PTP_1588 #gPTP #ArcGIS #批量操作 #地理空间分析 #c++高并发 #BoringSSL #Host #SSRF #云计算运维 # ARM服务器 # 鲲鹏 #uip #k8s #进程等待 #wait #waitpid # 离线AI #canvas层级太高 #canvas遮挡问题 #盖住其他元素 #苹果ios手机 #安卓手机 #调整画布层级 #万悟 #联通元景 #开发实战 #银河麒麟服务器系统 #CTF #SQL注入 #WAF绕过 #nosql #godot #文件上传漏洞 #节日 #静态链接 #链接 #ESP32编译服务器 #Ping #DNS域名解析 #moltbot #taro #Docsify #技术博客 # REST API #A2A #GenAI #游戏服务器断线 #bug # keep-alive #地理 #遥感 #系统降级 #华为P30 #Archcraft #磁盘配额 #存储管理 #形考作业 #国家开放大学 #系统运维 #NFC #智能公交 #服务器计费 #FP-增长 #outlook #错误代码2603 #无网络连接 #2603 #对话框 #Dialog #桌面开发 #MessageDialog #QInputDialog #解释器模式 #lucene #DAG #服务器解析漏洞 #云服务器选购 #Saas #SSH密钥 #知识点 #RIP #结构体与联合体 #ETL管道 #向量存储 #数据预处理 #DocumentReader #glances #毕设定制 #duckdb #smtp #smtp服务器 #PHP #intellij idea # 硬件配置 #cosmic #阿里云RDS #fs7TF #AI 推理 #NV #npu #coffeescript #ranger #MySQL8.0 #H3C #远程软件 #处理器 #AI教材写作工具 #AI创作技术 #教材编写实战 #创作效率优化 #ansys #ansys问题解决办法 #tornado # 网络延迟 # Connection refused #昭和仙君 #宠物 #teamviewer #信奥赛 #提高组 #csp-s #初赛 #真题 #网络 #Socket网络编程 #熵权法 #灰色关联分析 #传统服饰销售平台 #tekton # GLM # 服务连通性 #因果学习 #数据库架构 #数据恢复 #视频恢复 #视频修复 #RAID5恢复 #流媒体服务器恢复 #ftp #sftp # 轻量化镜像 # 边缘计算 #web server #请求处理流程 #代码规范 # 批量部署 #samba #opc模拟服务器 #农产品物流管理 #物流管理系统 #农产品物流系统 #农产品物流 #报表制作 #职场 #用数据讲故事 #语音生成 #4U8卡 AI 服务器 ##AI 服务器选型指南 #GPU 互联 #GPU算力 #VSCode # SSH # ms-swift #服务器线程 # SSL通信 # 动态结构体 #IPMB #远程管理 #个人助理 #数字员工 #pxe #奈飞工厂算法挑战赛 #free #vmstat #sar #xml #宝塔面板部署RustDesk #RustDesk远程控制手机 #手机远程控制 #铁路桥梁 #DIC技术 #箱梁试验 #裂纹监测 #四点弯曲 #结构与算法 #MinIO #麦克风权限 #访问麦克风并录制音频 #麦克风录制音频后在线播放 #用户拒绝访问麦克风权限怎么办 #uniapp 安卓 苹果ios #将音频保存本地或上传服务器 #IPv6 #TLS协议 #HTTPS #运维安全 #系统故障 #硬盘修复 #AI应用编程 #RGFNet多模态目标检测 #可见光-红外图像融合目标检测 #TGRS 2025顶刊论文 #YOLO多模态创新改进 #YOLO多模态融合属于发文热点 #闲置物品交易系统 #持续部署 #Minecraft #PaperMC #我的世界服务器 #机器翻译 #程序开发 #前端开发 #EN4FE #idc #自由表达演说平台 #演说 #STDIO传输 #SSE传输 #WebMVC #WebFlux #MCP SDK #esp32 #mosquito #国产开源制品管理工具 #Hadess #效率神器 #办公技巧 #自动化工具 #Windows技巧 #打工人必备 #范式 #llvm #数字孪生 #三维可视化 # Qwen3Guard-Gen-8B #多模态 #微调 #超参 #LLamafactory #随机森林 #运维 #batch #springboot3 #springboot3升级 #Spring Batch #升级Spring Batch #AI视频创作系统 #AI视频创作 #AI创作系统 #AI视频生成 #AI创作工具 #API #华为od机试 #华为od机考 #华为od最新上机考试题库 #华为OD题库 #od机考题库 #AI+ #coze #AI入门 #计组 #数电 #信息收集 #人流量统计 #roi区域识别 #车辆识别 #poll #Xshell #Finalshell #生物信息学 #组学 #Spire.Office # 模型微调 #开题报告 #RS232 #RS485 #RS422 #Matrox MIL #二次开发 #VMware创建虚拟机 #远程更新 #缓存更新 #多指令适配 #物料关联计划 #0day漏洞 #DDoS攻击 #漏洞排查 #Prometheus #嵌入式开发 # DIY主机 # 交叉编译 #2025年 #YOLOv13多模态创新改进 #YOLO多模态融合检测改进 #ICCV 2025多模态顶会 #LIF 局部光照感知融合模块 #效融合 RGB 与红外信息 #可见光与红外图像融合目标检测 #c #个人电脑 #大数据分析 #CS336 #Assignment #Experiments #TinyStories #Ablation #bochs #Termux #Samba #车载嵌入式 #SQL注入主机 #ARMv8 #内存模型 #内存屏障 #AE #protobuffer #结构化数据序列化机制 # 权限修复 #AITechLab #cpp-python #CUDA版本 #VMWare Tool #基础语法 #标识符 #常量与变量 #数据类型 #运算符与表达式 #Linly-Talker # 数字人 # 服务器稳定性 #网络安全大赛 #总体设计 #电源树 #框图 #向量嵌入 #算力建设 #boltbot #ACID #多文档事务 #分布式事务 #人脸活体检测 #live-pusher #动作引导 #张嘴眨眼摇头 #苹果ios安卓完美兼容 #声源定位 #MUSIC #海量数据存储 # 高温监控 #cesium #可视化 #ServBay #FunASR #语音转文字 #Unity #游戏服务器 #AI零代码开发 #敏捷开发 #自然语言编程 #软件开发范式变革 #智能体对传统行业冲击 #行业转型 #代理服务器 #个性化推荐 #BERT模型 #Qwen3-VL # 服务状态监控 # 视觉语言模型 #odoo #传媒 #appche #隐函数 #常微分方程 #偏微分方程 #线性微分方程 #线性方程组 #非线性方程组 #复变函数 #校园志愿者 #LangGraph 1.0 #企业级部署 #Kubernetes集群 #生产环境 #UDP服务器 #recvfrom函数 #量子计算 #Ward #ASR #SenseVoice #递归 #线性dp #日志模块 #音诺ai翻译机 #AI翻译机 # Ampere Altra Max #PN 结 #WAN2.2 #RWK35xx #语音流 #实时传输 #node #adobe #人形机器人 #人机交互 #gmssh #宝塔 #Proteus #UART #嵌入式系统 #统信操作系统 #POC #问答 #交付 #boosting #okhttp #库存管理 #边缘AI # Kontron # SMARC-sAMX8 #NSP #下一状态预测 #aigc #小艺 #搜索 #ClaudeCode #AICoder #人工智能编码助手 #RK3588 #RK3588J #评估板 #核心板 #resnet50 #分类识别训练 #cmmi #结对编程 #xcode #Linux多线程 #MOSFET #晶圆制造 #芯片制造 #AI工具集成 #容器化部署 #AI教程 #CMC #TCP/IP #美食 #基金 #股票 #开关电源设计 #SpringSecurity #鉴权 #Zigzag #ossinsight #小智 #分子动力学 #化工仿真 #session #vncdotool #链接VNC服务器 #如何隐藏光标 #haproxy #JADX-AI 插件 #电子电气架构 #系统工程与系统架构的内涵 #Routine #标准化流模型 #概率生成模型 #可逆变换 #概率密度变换 #starrocks #实例分割 #isic2016 #L6 #L10 #L9 #爬虫实战 #零基础python爬虫教学 #双色球历史开奖数据 #期号红球篮球开奖日期等 #结构化CSV存储 #Helm Chart #composer #symfony #java-zookeeper #grpc #Mycat #Navidrome #二维数组 #DuckDB #协议 #思爱普 #SAP S/4HANA #ABAP #NetWeaver #CVE-2025-13878 #CWE-617 #远程攻击 #测量 #网络安全计划 #数字时代 #机器人运动学 #PyKDL # child_process #Arduino BLDC #核辐射区域探测机器人 #电梯 #电梯运力 #电梯门禁 #数据报系统 #FPGA #动态数码管 #Verilog HDL #计时 #基于uni-app的 #校园二手物品交易系统 #AI写作工具 #教材编写效率提升 #AI教材编写 #教材编写难题解决 #教育领域AI应用 #Beidou #北斗 #SSR #远程桌面协议 #SPICE #保姆级教程 #电机正反转 #TMC2240 #DIR引脚控制 #分享 #PS #photoshop #jquery #fork函数 #进程创建 #进程终止 #anti-content #anti-content分析 #anti-content逆向 #ssh登录 #机器狗 #AGV #AMR #机器人乘梯 #OpenCode #技能系统 #技能模板 #DSL #解析器 #redisson #力扣 #前缀和 #Typora #状态图 #甘特图 #类图 #时序/序列图 #实体关系ER图