最新资讯

  • 手写 Linux 并发服务器,fork, pthread与 epoll 模型实战(包含深层原理剖析)

手写 Linux 并发服务器,fork, pthread与 epoll 模型实战(包含深层原理剖析)

2026-02-01 03:26:50 栏目:最新资讯 6 阅读

1. 最简单的服务器模型

在学习 Linux 网络编程时,我们通常接触的第一个服务器模型,就是单线程阻塞模型。只看它的名字其实已经能够明白这个模型的原理了,它的逻辑简单清晰:先创建一个 socket,再绑定端口,然后监听,最后在一个死循环里等待客户端连接。

1.1 单线程阻塞echo服务器

我们先来写一个最最基础的 echo 服务器,它的功能非常简单:就是把客户端发来的任何消息原封不动地再发回去。这也是为什么叫他echo服务器的原因。

#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int listen_fd, conn_fd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE];

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd == -1)
    {
        perror("socket listen");
        exit(1);
    }
    
    int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));//设置端口可复用
    
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(PORT);
    
    if(bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
    {
        perror("bind");
        exit(1);
    }
    
    if(listen(listen_fd, 5) == -1)
    {
        perror("listen");
        exit(1);
    }
    
    printf("服务器已启动,等待连接...
");

    conn_fd = accept(listen_fd, NULL, NULL);//阻塞等待客户端链接
    if(conn_fd == -1)
    {
        perror("accept");
        exit(1);
    }
    printf("客户端已连接
");

    ssize_t n;
    while ((n = read(conn_fd, buffer, BUFFER_SIZE)) > 0) //这里是阻塞的
    {
        write(conn_fd, buffer, n);//回写
    }

    close(conn_fd);
    close(listen_fd);
    return 0;
}

这段代码虽然简单,但它完整地展示了 Linux TCP 服务器的经典的五个步骤:socket -> bind -> listen -> accept -> read/write

其中还有几个值得注意的细节,我简单说一下:

第一个细节:端口复用。在socket之后,我加入了setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 。这一步至关重要,它允许我们的服务器在异常退出后,能够立即重启并重新绑定 8080 端口,而不会遇到 "Address already in use" 的错误。这是所有服务器的必备配置

第二个细节:网络字节序。在填充地址结构体serv_addr时,PORTINADDR_ANY 都要被 htons/htonl 函数处理。这是为了解决大小端问题。不同架构的 CPU 存储多字节整数的顺序可能不同。TCP/IP 协议栈规定了统一的网络字节序(大端)。这两个函数就是用来保证我们的数据符合标准,避免跨平台通信时出现数据解析错误。

第三个细节:这个模型最大的特点就是阻塞。程序首先会阻塞在 accept(),等待第一个客户端连接。连接成功后,程序会进入 while 循环,阻塞在 read(),等待客户端发送数据。正是这两个阻塞点,导致了它一次只能服务一个客户端的致命缺陷,也为我们后续的并发模型方向埋下了伏笔。

此外,为了展示最简单的服务器的功能到底有多么粗糙,我特意将 accept() 函数放在循环外面,这也就意味着,这个服务器一生只能服务一个客户端,当这个客户端断开连接时,服务器的运行也会结束。

下面我们来看看这个最简单的服务器到底都有哪些缺陷。

1.2 实验:致命的瓶颈

这个服务器看起来是能跑的,但他有一个致命的缺陷。我们可以通过一个简单的实验来看一下:

先运行上面的示例程序,就会显示 “服务器已启动…” 这些字,然后再开一个终端输入下面的命令:

telnet localhost 8080

就会显示 “客户端已连接” 。此时我在客户端输入一个 “hello” ,然后按回车,可以看到服务器在接收到 “hello” 之后又把他原封不动的发回给客户端了:

到这里,单线程阻塞echo服务器的功能就已经看到了。但如果我们再开一个终端尝试连接服务器呢?会发生什么事?

这里,我又开了一个终端连接服务器,如果尝试过的读者会发现这次服务器的那个终端并没有弹出 “客户端已连接” 这个表示链接成功的消息。此外,还能发现在这个新开的终端连接服务器,看似和前面那个客户端是相同的场景,但我们在输入 “hello” 并按下回车后,服务器并没有返回消息。这已经能够证明我们在这个终端上其实并没有连接到服务器

为什么呢?

这里暴露了两个致命问题

第一是无法并发:服务器的主线程在 accept 之后,就一头扎进了与第一个客户端通信的 while 循环里。只要这个客户端不主动断开,程序就永远没有机会去处理新的连接请求。

第二是一次性服务:更糟糕的是,一旦第一个客户端断开连接,while 循环结束,整个服务器程序也会跟着退出。

这种单线程、单任务、一次性的模型,在任何实际应用中都是不可接受的。我们需要让服务器:能同时服务多个客户端 (并发)还能 7x24 小时运行,而不是服务完一个就退出

2. 多进程模型

为了解决单线程模型的两大缺陷,我们自然而然地想到了 Linux 提供的多任务机制。最经典、最简单的就是多进程

2.1 改进思路

前面的单线程阻塞模型问题主要出在无法并发无法多次服务,因此我们主要针对这两点进行改进。

父进程,也就是主进程,它在一个while循环里面,主要负责接收 accept() ,也就是接收客户端连接请求。

子进程,负责处理客户端发来的信息。

他们的分工,我在这里简要总结一下:父进程一旦接收到客户端连接请求,立刻fork出一个子进程,然后把这个客户端交给子进程去处理,父进程自己继续去等待其他客户端了连接。

从这个改进思路上来看,已经实现了并发多次服务的两个目标。下面我们来关注一下这个模型的实现。

2.2 多进程 echo 服务器

上面已经讲了改进思路,我们废话不多说,直接贴出代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8080
#define BUFFER_SIZE 1024

int main() 
{
    int listen_fd, conn_fd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE];
    pid_t pid;

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(listen_fd == -1)
	{
		perror("socket listen");
		exit(1);
	}

	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
	if(bind(listen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1)
	{
		perror("bind");
		exit(1);
	}

    if(listen(listen_fd, 5) == -1)
	{
		perror("listen");
		exit(1);
	}

    printf("服务器已启动,等待连接...
");

    while (1) 
    { 
        conn_fd = accept(listen_fd, NULL, NULL);
        if (conn_fd < 0) 
		{
            perror("accept");
            continue; //出错了没事,继续等下一个
        }

        pid = fork();

        if(pid < 0) 
		{
            perror("fork");
            close(conn_fd);
            continue;
        }
		else if(pid == 0) //子进程
		{
            close(listen_fd); 

            printf("子进程%d为新客户端服务(fd=%d)...
", getpid(), conn_fd);

            ssize_t n;
            while (((n = read(conn_fd, buffer, BUFFER_SIZE))) > 0) 
			{
                write(conn_fd, buffer, n);//回写的字节数一定要是read读到的字节数
            }
            
            printf("客户端断开,子进程%d退出。
", getpid());
            close(conn_fd);
            exit(0); 
        } 
		else 
		{
            close(conn_fd); 
        }
    }

    close(listen_fd); // 理论上走不到这里,因为父进程一直在循环里面
    return 0;
}

运行代码,看看效果怎么样:

这次我运行服务器后,直接开了三个终端连接上服务器,可以看到,服务器所在终端已经弹出了客户端已连接成功的消息:

我们在来看看这三个客户端的情况:


通过运行结果可以看到,这三个客户端都可以收到服务器回传的消息,说明我们已经达到了开始的目标。

到这儿,可能有人会提出问题,为什么服务器端显示连接上的三个客户端的文件描述符 fd 都是 4 呢?其实这并不是发生了错误,而是一个正常现象,来听我详细解释:

当父进程调用 fork 时,内核会为子进程创建一个几乎一模一样的内存空间和上下文,在这里我们只关注于文件描述符表。每个进程都有自己独立的文件描述符表,在 fork 的那一瞬间,子进程也得到了和父进程一模一样的文件描述符表

好,理论讲完了,我们来关注一下过程,到底是什么原因导致了三个相同的文件描述符呢?

首先,在进程中,文件描述符的 0,1,2 已经默认被标准输入,标准输出和标准错误占据了,这时,进程进行 socket ,把返回的值(也就是3)赋给 listen_fd

然后,当第一个客户端连接时,父进程调用 accept ,返回一个新的 conn_fd ,由于 3 已经被占用了,所以 conn_fd 只能为 4。

之后,父进程调用fork创建第一个子进程(PID:11375),这个子进程得到了父进程完整的文件描述符表,子进程的fd=4也指向了和父进程相同的 TCP 连接

接着,printf("子进程%d为新客户端服务(fd=%d)... ", getpid(), conn_fd);打印出的fd自然就是 4 了,因为在父进程那就是 4,从来没变过。

再然后,父进程关闭了自己的 fd=4 ,因为这对他没用,同样 listen_fd对子进程也没用,所以子进程关了 listen_fd

这时,当第二个客户端(PID = 11422)请求连接时,父进程的fd=4又空出来了,于是在父进程这里,第二个客户端有拿到了 fd=4 这个文件描述符,然后再次fork,子进程拿到的也是文件描述符fd=4对应的第二个客户端…

所以说,父进程每次将客户端交给子进程后,就会关闭文件描述符 4 ,这个文件描述符 4 空闲出来,下一次有客户端连接用的又是文件描述符 4 ,因此才导致了上面的情况。所以说,这其实是正常现象。

2.3 僵尸进程

多进程模型完美解决了并发问题,看起来似乎无懈可击。但它引入了一个新的、更隐蔽的、可能导致严重后果的东西——**僵尸进程 **。

我们来分析一下上面的程序,如果客户端正常断开连接,那么对应的子进程会执行exit(0),子进程退出后,内核会保留它的 PID 和退出状态等信息,等待父进程过来收尸,但是,父进程此时正忙着在while循环里面accept新的连接,压根就没有时间。

最后,这些无人认领的尸体会越来越多,堆积在内核的进程表里。虽然它们不占很多内存,但会耗尽 PID 资源。当 PID 用完,系统将无法创建任何新进程,最终只能重启。

下面,我们来验证一下僵尸进程的存在:

我来解释一下这三张图,第一张图中我退出了 PID 为 11375 的子进程负责的客户端,然后又以相同的方式退出了其余的两个子进程负责的客户端。

第二张图显示了三个子进程已经执行exit(0);退出了。而父进程还在继续运行,此时父进程在accept等待新的客户端连接,并没有为子进程收尸,因此他们变成了僵尸进程。

第三张图是我查询僵尸进程的结果,图中显示,PID为 11375 , 11422 , 11490 的三个进程此时的状态(STAT)为 Z+,如果一个进程的状态为Z,表示这个进程是僵尸进程,如果是Z+,表示这个进程是一个属于前台进程组的僵尸进程。

一般情况下,如果想要清理一个僵尸进程,最好的办法是杀死它的父进程。但这种方法在这里显然是不行的。

试想一下,一台服务器正在运行,由于其中的几个进程退出后没有及时清理,产生了僵尸进程,而此时你想关闭这台服务器来进行清理僵尸进程,这等于直接断开正在与服务器通信的所有客户端,造成的损失是不可估量的。

下面我介绍一种比较优雅的方法,在服务器端不退出的情况下回收子进程。

2.4 SIGCHLD 信号

如何让父进程在不阻塞 accept 的情况下,及时回收子进程呢?答案是信号

当一个子进程终止时,内核会给其父进程发送一个 SIGCHLD 信号。我们只需要为父进程注册一个处理这个信号的函数即可。

我们需要引入头文件,然后在main函数的前面写一个sigchld_handler函数,此外,还要在main函数里面注册这个信号,放在main函数第一行就行。其他部分不需要改变。

为了简便,我这里只给出最关键的部分,补全到上面多进程模型的代码里面就行了:

#include  

void sigchld_handler(int sig) 
{
    while (waitpid(-1, NULL, WNOHANG) > 0);//非阻塞等待所有子进程
}

int main()
{
    signal(SIGCHLD, sigchld_handler);
    
    //........中间部分不变........
    
    return 0;
}

代码修改之后,我又重新运行了一次。这次我直接创建了三个客户端然后退出。此时父进程还在运行,去查一下发现并没有僵尸进程,这就说明我们的信号处理方法已经生效了。


2.5 补充知识

考虑到可能会有人好奇,从内核向父进程发送SIGCHLD信号到父进程回收僵尸进程,这中间到底是怎样运转的。我增加了这一节,下面详细解释一下。

当子进程执行完毕退出后,内核将其标记为僵尸进程,然后内核去查找该子进程的父进程,并向父进程发送SIGCHLD信号。

父进程此时大概率阻塞在 accept() 上,当SIGCHLD信号到达时,内核会中断父进程的行为,accept() 会立即返回 -1,并将 errno 设置为 EINTR。除此之外,内核还会修改父进程的程序计数器(PC)栈(STACK) ,使得父进程醒来后能从我们的信号处理函数sigchld_handler开始执行。当信号处理函数执行完 return 时,实际上是跳到了内核预设的一段跳板代码,这段代码会调用 sys_sigreturn 系统调用,通知内核恢复父进程之前的上下文,从而让进程醒来后继续从被SIGCHLD信号中断的地方执行。

而在信号处理函数内部,我们调用了 waitpid(-1, NULL, WNOHANG)。-1表示回收任何一个已经终止的子进程,WNOHANG表示非阻塞,没有僵尸进程回收的话就直接返回,防止父进程的main函数那边等太长时间。

为了方便大家理解这个过程,我们可以在前面代码的基础上进行修改,如下所示,在perror上面加了一个if判断:

         conn_fd = accept(listen_fd, NULL, NULL);
		if (conn_fd < 0) 
		{
			if(errno == EINTR)
			{
				printf("accept被SIGCHLD信号中断了,这是正常现象,程序继续运行...
");
			}
			perror("accept");
            continue; //出错了没事,继续等下一个
        }

但是就这样printf的内容是不会按照我们预想的那样打印出来的。因为在默认的signal情况下,内核会让父进程回到accept执行之前的状态,相当于重新运行accept,如果这次没有被SIGCHLD信号中断的话,accept也不会返回-1,errno也不会被置为EINTR,退一万步说,就算再次被SIGCHLD信号中断,下次父进程醒来还是要重新执行accept,也就是说在这种模式下printf的内容是永远不会被打印出来的。

要想看到printf的内容,证明errno确实被置为EINTR了,我们必须采用更高级的信号处理方式。为了方便大家复现,这次给出完整代码吧:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8080
#define BUFFER_SIZE 1024

void sigchld_handler(int sig)
{
	while(waitpid(-1,NULL,WNOHANG)>0);
}

int main() 
{
    //--------------------重点关注这里-----------------//
	struct sigaction sa;
	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	if (sigaction(SIGCHLD, &sa, NULL) == -1) 
	{
        perror("sigaction error");
        exit(1);
    }
    //------------------------------------------------//

    int listen_fd, conn_fd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE];
    pid_t pid;

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(listen_fd == -1)
	{
		perror("socket listen");
		exit(1);
	}

	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
	if(bind(listen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1)
	{
		perror("bind");
		exit(1);
	}

    if(listen(listen_fd, 5) == -1)
	{
		perror("listen");
		exit(1);
	}

    printf("服务器已启动,等待连接...
");

    while (1) { 
        conn_fd = accept(listen_fd, NULL, NULL);
        if (conn_fd < 0) 
		{
            //-------------------------------还有这里-----------------
			if(errno == EINTR)
			{
				printf("accept被SIGCHLD信号中断了,这是正常现象,程序继续运行...
");
			}
            //--------------------------------------------------------
			perror("accept");
            continue; //出错了没事,继续等下一个
        }

        pid = fork();

        if(pid < 0) 
		{
            perror("fork");
            close(conn_fd);
            continue;
        }
		else if(pid == 0) 
		{
            close(listen_fd); 

            printf("子进程%d为新客户端服务(fd=%d)...
", getpid(), conn_fd);

            ssize_t n;
            while (((n = read(conn_fd, buffer, BUFFER_SIZE))) > 0) 
			{
                write(conn_fd, buffer, n);
            }
            
            printf("客户端断开,子进程%d退出。
", getpid());
            close(conn_fd);
            exit(0); 
        } 
		else 
		{
            close(conn_fd); 
        }
    }

    close(listen_fd); // 理论上走不到这里
    return 0;
}

运行后结果如下,这次我们可以看到,printf的内容和perror的内容都被打印出来了,因为默认情况下 signal() 会隐含 SA_RESTART 标志,导致系统调用自动重启。我们把sa.sa_flags设为 0 表示不自动重启,我们才能在 accept 返回处捕获 EINTR

3. 多线程模型

在解决了僵尸进程后,我们的多进程服务器已经非常健壮了。但是,如果我们要面对成千上万个并发连接,每来一个连接就 fork() 一个进程,这种方法开销实在太大了

我们需要一种更轻量的方案——多线程

3.1 改进思路

进程拥有独立的内存空间(堆、栈、代码段)。创建一个进程,内核需要复制页表、文件描述符表等,成本昂贵。

线程共享进程的内存空间。创建一个线程,只需要分配一个小小的栈空间,成本极低。

了解了进程和线程的区别,我们的改进思路就非常明确了,如下:

主线程负责accept()等待客户端连接。每当一个客户端连接上,就pthread_create()一个工作线程去负责。

工作线程负责处理对应客户端的信息。

3.2 线程模型的优缺点

线程模型的优点:

线程创建速度比进程快 10~100 倍。

线程间共享全局变量和堆内存,不需要复杂的 IPC(管道、共享内存等)。

线程模型的缺点:

一个线程崩溃,整个进程(包括所有其他线程)都会挂掉。而多进程模型中,一个子进程崩了,不影响父进程和其他子进程。

共享资源(如全局变量)需要加锁,写不好容易死锁或数据竞争。

虽然比进程轻,但如果是 1 万个连接,依然需要 1 万个线程。操作系统的调度器会被累死,内存也会被撑爆。在 Linux 中,每个新线程的默认栈大小通常为 8 MB,1万个线程栈就是 80 GB。

3.3 小总结

整体上来看,多线程模型和多进程模型的思路其实是相同的,多线程模型虽然减轻了创建开销,但一个连接一个线程 的本质没有变。面对海量并发,我们必须彻底抛弃这种方式,转向一种全新的思维模式

下一章要介绍的就是 Linux 网络编程的终极武器——I/O 多路复用 (epoll)

4. I/O多路复用

虽然多线程模型减轻了创建和销毁的开销,但本质上它依然遵循一个连接一个线程的思路。当并发连接数上升到 1 万甚至 100 万时,这种模型会面临两个无法逾越的障碍:

第一个是内存爆炸,1 万个线程,每个线程栈 8MB,光栈空间就需要 80GB 内存。

第二个是调度崩溃,操作系统在成千上万个线程之间进行上下文切换,CPU 的时间全花在切换上,而不是干正事儿上。

因此,我们需要一种机制,能够用一个线程监控成千上万个连接。这就是 I/O 多路复用

4.1 从线性轮询到事件驱动

epoll 出现之前,Linux 使用 selectpoll。它们虽然能实现多路复用,但在内核实现上存在本质的缺陷。

selectpoll 的工作机制非常原始。每次调用它们,都需要将所有要监控的文件描述符集合从用户态完整拷贝到内核态

内核在检测时,会遍历整个集合**(O(N) 复杂度)。如果有事件发生,内核只是简单地标记有事件已经就绪,但不会告诉说明到底是哪一个。这也就是说,select 返回后,用户态程序还需要再遍历一遍**整个集合,才能找到真正需要处理的那个文件描述符。

当连接数达到 10万,但活跃连接只有 1 个时,select 依然要空转 10万次,这造成了大量的性能浪费。并且select 受限于 FD_SETSIZE (默认是 1024),是无法处理海量连接的。

epoll的出现完美解决了上面的问题。epoll在内核设计了两个核心的数据结构

第一个是红黑树epoll_create 会在内核开辟一块空间,当我们调用 epoll_ctl 添加 socket 时,内核会将这个 socket 节点插入到一棵红黑树中。红黑树的查找、插入、删除复杂度均为 O(logN),即使管理百万级连接,效率依然极高。且这棵树一直在内核里面,无需像 select 那样每次都要重复拷贝文件描述符集合。

第二个是就绪链表,内核为红黑树中的每个 socket 注册了一个回调函数。当网卡收到数据,中断处理程序触发回调,自动将该 socket 节点拷贝到一个**双向链表(也就是就绪链表)**中。

而**epoll_wait要干什么呢?它只需要检查那个就绪链表是否为空**,如果不为空,直接把链表里的节点复制回用户态。

下面我列个表格对比一下,这几种I/O多路复用的方式:

4.2 核心代码实现

下面是一个基于 epoll单线程并发服务器。请注意观察,代码中不再有 forkpthread_create,所有的连接都在同一个 while(1) 循环中被串行处理。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8080
#define BUFFER_SIZE 1024
#define MAX_EVENTS 10

int main()
{
	int listen_fd,conn_fd,epoll_fd,n_read;
	struct sockaddr_in server_addr;
	char buffer[BUFFER_SIZE];

	struct epoll_event ev,events[MAX_EVENTS];

	listen_fd = socket(AF_INET,SOCK_STREAM,0);
	if(listen_fd == -1)
	{
		perror("socket listen");
		exit(1);
	}
	printf("监听socket创建成功
");

	int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));//设置端口可复用

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1)
	{
		perror("bind");
		exit(1);
	}
	printf("绑定成功
");

	if(listen(listen_fd,5) == -1)
	{
		perror("listen");
		exit(1);
	}

	epoll_fd = epoll_create1(0);
	if(epoll_fd == -1)
	{
		perror("epoll_create");
		exit(1);
	}
	printf("epoll实例创建成功
");

	ev.events = EPOLLIN;
	ev.data.fd = listen_fd;
	if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_fd,&ev) == -1)
	{
		perror("epoll_ctl");
		exit(1);
	}
	printf("listen_fd添加成功
");
	printf("服务器正在监听%d端口....
",PORT);

	while(1)
	{
		n_read = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);//阻塞等待
		if(n_read == -1)
		{
			perror("epoll_wait");
			exit(1);
		}

		for(int i=0;i<n_read;i++)
		{
			if(events[i].data.fd == listen_fd)//有新的连接到来
			{
				conn_fd = accept(listen_fd,(struct sockaddr *)NULL,NULL);
				printf("接受新的连接,fd = %d
",conn_fd);
				ev.events = EPOLLIN;
				ev.data.fd = conn_fd;
				epoll_ctl(epoll_fd,EPOLL_CTL_ADD,conn_fd,&ev);
			}
			else
			{
				int client_fd = events[i].data.fd;
				ssize_t n = read(client_fd,buffer,BUFFER_SIZE);

				if(n == 0)
				{
					printf("客户端fd = %d关闭了连接
",client_fd);
					epoll_ctl(epoll_fd,EPOLL_CTL_DEL,client_fd,NULL);
					close(client_fd);
				}
				else if(n > 0)
				{
					write(client_fd,buffer,n);
				}
				else
				{
					perror("read");
					close(client_fd);
				}
			}
		}
	}
	close(listen_fd);
	return 0;
}

这段代码才用的是LT水平触发)模式,在while循环之前,我们需要把监听socket(listen_fd)添加到我们需要关注的事件中。

下面简要解释一下这段代码的核心逻辑。

进入while循环后,epoll_wait就会阻塞等待,当它返回时,events数组中就存放着真正有事件发生的文件描述符。相比于 select 需要遍历整个文件描述符集合,epoll 直接把需要处理的文件描述符单独拎出来给我们,这就是它在海量连接下性能不衰减的原因。

然后我们会进入for循环,它会把events数组中需要处理的文件描述符一个一个拿出来,判断他们到底是哪种类型的,是有新的连接到来,还是说旧的连接发消息了,这个判断过程体现在if判断中。

如果有新的连接到来,那我们就accept,并且把这个新链接上的文件描述符添加到我们需要关注的事件中。

如果是旧的连接在发消息,那我们就先read,把这个消息存放在buffer中。在这之后,我们必须要判断一下read的返回值,因为客户端退出会体现在这里。如果客户端退出,read会返回 0,这时我们要把相应的文件描述符从我们需要关注的事件中删除,然后关闭这个文件描述符。如果是正常读写,那我们就再给他回写过去。如果真的出错,那就提示就完事儿了。

4.3 效果展示与新的瓶颈

为了展示这个单线程epoll的效果怎么样,我直接开了三个客户端连接它,并且发送hello都可以正常回写,运行结果如下:

但是请看这里:

				else if(n > 0)
				{
					write(client_fd,buffer,n);
				}

这是我们在接收到客户端消息后进行的处理,只有一条简单的write系统调用。试想一下,如果这里的业务逻辑变成了视频解码,或者复杂的数据库查询,需要消耗 1 秒,会发生什么情况呢?

因为我们只有一个线程在死循环里处理任务。当它正在处理那个耗时 1 秒的任务时,epoll_wait 无法被调用,新的连接进不来,其他客户端的消息也卡在缓冲区里无法处理。整个服务器在这一秒时间里会处于 “假死” 状态。

单线程 epoll 虽然解决了 I/O 的并发,但无法利用多核 CPU 处理计算密集型任务。

因此,我们需要将 epoll (只负责 I/O)线程池 (只负责处理) 结合起来。这就是最终形态——Reactor 模型

5. epoll + 线程池

为了解决单线程 epoll 无法利用多核 CPU,且计算任务会阻塞 I/O 这个痛点,我们需要将 I/O 处理业务逻辑 彻底分离。这也是现代高性能服务器(如 Nginx,Netty)通用的 Reactor 模型

5.1 模型设计

我们引入线程池 来负责具体的业务计算,主线程只负责 I/O 调度

主线程:负责 epoll_waitaccept 新连接、read 数据。收到数据后,立刻封装成一个任务,扔进任务队列。

任务队列:连接主线程与工作线程的桥梁。这里我们复用了之前项目中手搓的高性能 RingBuffer。感兴趣的朋友可以去我前面发的文章看一下这个RingBuffer的具体实现,这里我就不再详细描述了。

工作线程:先从队列取任务,然后执行比较耗时的逻辑(如数据库查询、加密解密),最后将结果write 回客户端。它能充分利用多核 CPU 进行并行计算。

下面这张图是我画的一张示意图,主线程负责将任务pushRingBuffer,工作线程获取任务并处理完毕后,直接将响应结果写入客户端 Socket

5.2 Ring Buffer 实现

我直接将前面那篇《高并发异步日志库》的 RingBuffer 进行简单的修改,如下:

#ifndef RING_BUFFER_H
#define RING_BUFFER_H

#include 
#include 

#define BUFFER_SIZE 1024

//任务结构体
typedef struct {
    int client_fd;           // 记录是谁发的请求
    char data[BUFFER_SIZE];  // 具体数据
} Task;

// 环形缓冲区管理器
typedef struct {
    Task *entries;  // 指向 malloc 的大数组
    int capacity;   // 总容量
    
    int head;
    int tail;
    int count;

    pthread_mutex_t mutex;
    pthread_cond_t cond_producer;
    pthread_cond_t cond_consumer;

    bool is_running; // 优雅退出
} RingBuffer;

void rb_init(RingBuffer *rb, int capacity);
void rb_push(RingBuffer *rb, const Task *entry);
int  rb_pop(RingBuffer *rb, Task *entry);
void rb_stop(RingBuffer *rb);
void rb_destroy(RingBuffer *rb);

#endif

ring_buffer.c文件里面的LOG也要改为TASK,但代码逻辑不需要改变。

5.3 核心代码实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "ring_buffer.h"

#define PORT 8080
#define MAX_EVENTS 10
#define THREADS_NUM 4  //四个线程处理任务

volatile sig_atomic_t  g_is_running = 1;
RingBuffer *g_rb = NULL;

void sig_handler(int sig)
{
	g_is_running = 0;

	if(g_rb)
	{
		rb_stop(g_rb);
	}
}

void *work_thread(void *arg)
{
	RingBuffer *rb = (RingBuffer *)arg;
	Task task;

	while(rb_pop(rb,&task))//优雅退出
	{
		printf("工作线程%ld拿到任务,处理fd = %d
",pthread_self(),task.client_fd);

		sleep(5);//模拟耗时的运算

        int len = strlen(task.data);
		for(int i=0;i<len;i++) 
		{
			task.data[i] = toupper(task.data[i]);
		}
		write(task.client_fd,task.data,strlen(task.data));
	}
	return NULL;
}

int main()
{
    signal(SIGPIPE, SIG_IGN);
	signal(SIGINT,sig_handler);

	RingBuffer rb;
	rb_init(&rb,10);
	g_rb = &rb;    //让全局指针指向main的rb

	pthread_t threads[THREADS_NUM];
	for(int i=0;i<THREADS_NUM;i++)
	{
		pthread_create(&threads[i],NULL,work_thread,(void *)&rb);
	}

	int listen_fd,conn_fd,epoll_fd,n_read;
	struct sockaddr_in server_addr;

	struct epoll_event ev,events[MAX_EVENTS];

	listen_fd = socket(AF_INET,SOCK_STREAM,0);
	if(listen_fd == -1)
	{
		perror("socket listen");
		exit(1);
	}
	printf("监听socket创建成功
");
    
    int opt = 1;
	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1)
	{
		perror("bind");
		exit(1);
	}
	printf("绑定成功
");

	if(listen(listen_fd,5) == -1)
	{
		perror("listen");
		exit(1);
	}

	epoll_fd = epoll_create1(0);
	if(epoll_fd == -1)
	{
		perror("epoll_create");
		exit(1);
	}
	printf("epoll实例创建成功
");

	ev.events = EPOLLIN;
	ev.data.fd = listen_fd;
	if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_fd,&ev) == -1)
	{
		perror("epoll_ctl");
		exit(1);
	}
	printf("listen_fd添加成功
");
	printf("服务器正在监听%d端口....
",PORT);

	while(g_is_running)
	{
		n_read = epoll_wait(epoll_fd,events,MAX_EVENTS,500);//500ms超时
		if(n_read < 0)
		{
			continue;
		}

		for(int i=0;i<n_read;i++)
		{
			if(events[i].data.fd == listen_fd)//有新的连接到来
			{
				conn_fd = accept(listen_fd,(struct sockaddr *)NULL,NULL);
				printf("接受新的连接,fd = %d
",conn_fd);
				ev.events = EPOLLIN;
				ev.data.fd = conn_fd;
				epoll_ctl(epoll_fd,EPOLL_CTL_ADD,conn_fd,&ev);
			}
			else
			{
				int client_fd = events[i].data.fd;
				Task new_task;
				new_task.client_fd = client_fd;

				ssize_t n = read(new_task.client_fd,new_task.data,BUFFER_SIZE-1);

				if(n == 0)
				{
					printf("客户端fd = %d 关闭了连接
",client_fd);
					epoll_ctl(epoll_fd,EPOLL_CTL_DEL,client_fd,NULL);
					close(client_fd);
				}
				else if(n > 0)
				{
					new_task.data[n] = '';
					rb_push(&rb,&new_task);
				}
				else
				{
					perror("read");
					close(client_fd);
				}
			}
		}
	}
	printf("主循环退出,准备关闭服务器
");
	for(int i=0;i<THREADS_NUM;i++)
	{
		pthread_join(threads[i],NULL);
	}

	printf("所有线程已经全部退出
");
	close(listen_fd);
	rb_destroy(&rb);
	printf("服务器已经关闭
");

	return 0;
}

这段核心代码虽然不长,但它诠释了 Reactor 模型的核心思想。下面我要解读一下关键的部分:

主线程运行在 epoll 事件循环中,当 epoll 通知有数据时,主线程调用 read 将数据从内核读到用户态内存。但它自己不进行任何业务处理,而是立刻将 client_fd 和数据封装成一个 TaskpushRingBuffer

4 个工作线程从 RingBuffer 中获取任务。如果队列为空,它们会挂起,不占用 CPU,等待条件变量唤醒。这里我特意用 sleep(5) 模拟了耗时的业务逻辑。在前面的单线程模型中,这会导致服务器卡死 5 秒。但在本模型中,这只是其中一个工作线程在睡觉,主线程依然在飞快地接收新请求,其他工作线程依然在忙自己的事情。业务处理完毕后,工作线程直接调用 write 将结果发回给客户端,到这里完成了闭环。

还有,可能有人注意到了,在 read 时,我使用了 BUFFER_SIZE - 1,预留了一个字节给字符串结束符 防止缓冲区溢出

如果客户端突然断开,工作线程还往里写数据,内核会直接发信号杀掉进程。因此我还在main 函数开头添加了 signal(SIGPIPE, SIG_IGN),防止因客户端意外断开导致服务器写入时崩溃。

此外,我还实现了优雅退出,当你在服务器端按下Ctrl+C时,程序并不会立刻退出,而是去执行sig_handler信号处理函数。返回后主线程会跳出while循环,因为在函数rb_stop中已经通知工作线程结束了,因此主线程在main函数中要进行回收,回收完之后关闭。

5.4 效果验证

为了验证这个模型的效果,运行服务器端后,我还是像前面一样开了三个客户端并连接上服务器。然后我先给这三个客户端每个都分别输入一段内容,但是先不按回车,等输入完了,飞快的切换客户端并按下回车。最终会发现,大约5秒后,这三个客户端是同时收到回复的,这完全说明了这个模型的并发性。

尽管每个任务都要睡 5 秒,但我们可以看到,主线程依然能流畅地接受新的连接请求,没有丝毫卡顿。

观察服务器端的日志,处理 fd=5, fd=6, fd=7 的是不同的工作线程。这说明线程池正在全速运转,正在进行真正的并行工作。


最后直接在服务器端按下Ctrl+C,可以看到优雅退出的信息,工作线程也会随之结束。

6. 标题有六个字

最后再回看正篇文章。如果用的是 fork ,1 万个连接就是 1 万个进程,光是上下文切换就够 CPU 吃一壶得了。而用我们现在的 Reactor 模型,1 万个连接在 epoll 眼里不过是红黑树上的 1 万个节点,只有真正活跃的那几十个连接才会触发回调。

我把完整的 Reactor 模型的源码放在 github 里面了,有需要的可以自取,感觉有帮助的朋友也可以点上一手关注

👉源码点击这里

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

搜索文章

Tags

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