一、并发服务器的作用

1、可以去处理高并发请求

2、降低延迟以及去处理IO密集的任务

二、并发服务器的三种模型

1、多线程并发服务器

原理

我们可以理解它为是一个主从架构。主线程负责接收客户端连接,每来一个客户端就创建一个新线程,由该线程专门处理这个客户端的通信。

流程

1、主线程负责监听listen()我们的客户端连接请求accept()。

2、之后为每个客户端去创建一个新的线程或者创建一个线程池,去线程池中唤醒或者分配一个新的线程。(子线程)

3、然后每个线程处理一个读写任务recv()/send()。主要负责与客户端进行通信的,处理客户端的请求,并回应我们的一个响应。

4、使用完会进行一个销毁,或者就是线程池进行的一个反复利用。close()

socket(AF_INET, SOCK_STREAM, 0);
//参数(地址族,套接字类型,协议)

地址族:
AF_INET      // IPv4
AF_INET6     // IPv6  
AF_UNIX      // 本地通信(Unix域套接字)
AF_PACKET    // 链路层直接访问

套接字类型:
SOCK_STREAM   // 流式套接字 → TCP(可靠、有序、面向连接)
SOCK_DGRAM    // 数据报套接字 → UDP(不可靠、无序、无连接)
SOCK_RAW      // 原始套接字 → IP层直接操作
SOCK_SEQPACKET // 有序分组套接字 → SCTP

 协议:
0       自动选择(SOCK_STREAM → TCP,SOCK_DGRAM → UDP)

2、多进程并发服务器

原理

通过创建多个子进程,来同时处理多个客户端请求的一种服务端架构。

核心思想是利用我们操作系统的多进程机制,将每个客户端的请求分配给独立的子进程来进行处理,从而实现我们的一个并发处理。

流程

1、主进程监听listen()和接受accept()连接

2、为每个客户端创建fork()一个子进程,父进程(主进程)继续回去 accept() 等待下一个客户端

3、子进程处理读写任务,子进程调用 recv() 接收客户端数据,处理完后调用 send() 发回响应

4、子进程销毁,客户端断开后,子进程调用 close() 关闭连接,子进程调用 exit(0) 退出销毁,父进程回收子进程资源

3、IO多路复用并发服务器

原理

一个线程同时监控所有客户端,谁有数据就处理谁,没有就继续监控,不像多线程那样每个客户端配一个线程傻等。

通过单线程去监控多个文件描述符socket(),利用selected系统调用,实现我们的一个非阻塞轮询,当我们任意一个被监控的一个socket就绪的时候(比如说可读可写或异常的时候)selected会返回并通知我们的程序去处理这些事件。

流程

1. 主线程创建监听套接字,调用 listen() 开始监听

2. 调用 select() 或 epoll() 同时监控所有套接字

  • 包括监听套接字和所有已连接的客户端套接字

  • 这个函数会阻塞,直到有一个或多个套接字有数据可读

3. 当 select()/epoll() 返回时,遍历所有有事件的套接字

  • 如果是监听套接字有事件:调用 accept() 接受新客户端,把新的客户端套接字加入监控列表

  • 如果是客户端套接字有事件:调用 read()/recv() 读取数据,处理业务,调用 send() 发回响应

4. 回到步骤2,继续循环监控

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐