深入了解linux下TCP并发服务器和IO模型的实现

一、整体框架

在网络编程中,服务器的架构可以根据需求不同而有所不同。主要有以下几种框架:

  1. 单循环服务器:同一时刻只处理一个客户端的请求,通常使用传统的阻塞式编程模型。这种模型简单易实现,但处理能力有限,无法有效应对多个客户端的并发请求。

  2. 并发服务器:能够处理多个客户端的请求。通过引入多线程或多进程等技术来实现并发处理,从而提高服务器的处理能力和响应速度。并发服务器可以分为以下几种实现方式:

  • 多进程:每个客户端连接由一个独立的进程处理。常用于需要隔离处理环境的场景。

  • 多线程:每个客户端连接由一个独立的线程处理。适用于需要较高资源共享的场景。

  • IO多路复用:使用单个进程/线程处理多个连接,通过高效的IO多路复用机制来管理多个并发连接。适用于需要高并发处理的场景。

二、服务器

2.1 单循环服务器 vs 并发服务器

  • 单循环服务器:

  • 处理一个客户端的请求时,其他客户端的请求必须等待,导致处理效率低。

  • 简单易实现,但不适合高并发场景。

  • 并发服务器:

  • 可以同时处理多个客户端的请求。通过创建多个进程或线程来处理不同的客户端连接,从而提高服务器的并发处理能力。

  • UDP协议由于是无连接的,天然支持并发处理。每个数据报独立处理,不需要建立持久连接。

  • TCP协议是面向连接的,传统上一个TCP服务器只能处理一个客户端连接。但通过多进程或多线程的方式,可以实现TCP并发服务器。

三、TCP并发服务器

3.1 多进程

多进程模型的服务器在接收到连接请求时,会创建一个新的进程来处理每一个客户端连接。以下是基本的执行流程:

  1. socket():创建一个新的套接字。

  2. bind():将套接字绑定到特定的IP地址和端口号。

  3. listen():将套接字设置为监听模式,等待客户端的连接请求。

  4. accept():接受客户端的连接请求,返回一个新的套接字用于与客户端通信。

  5. fork():创建一个子进程来处理新的客户端连接。父进程继续监听新的连接请求。

3.2 多线程

多线程模型的服务器在接收到连接请求时,会创建一个新的线程来处理每一个客户端连接。以下是一个示例代码:

/*************************************************************************

> File Name: pthread.c

> Author: yas

> Mail: rage_yas@hotmail.com

> Created Time: Tue 27 Aug 2024 02:48:41 PM

************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <string.h>

#include <arpa/inet.h>

void *doSth(void *arg) {

int connfd = *((int *)arg);

while (1) {

char buff[1024] = {0};

ssize_t size = recv(connfd, buff, sizeof(buff), 0);

if (size <= 0) {

break;

}

printf("cli--------->%s\n", buff);

strcat(buff, "----->ok!");

send(connfd, buff, strlen(buff), 0);

}

close(connfd);

return NULL;

}

int conct(const char *ip, unsigned short port) {

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd == -1) {

return -1;

}

struct sockaddr_in ser;

ser.sin_family = AF_INET;

ser.sin_port = htons(port);

ser.sin_addr.s_addr = inet_addr(ip);

int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));

if (ret == -1) {

perror("fail bind");

return -1;

}

ret = listen(sockfd, 120);

if (ret == -1) {

return -1;

}

return sockfd;

}

int main(int argc, char *argv[]) {

int connfd = 0;

pthread_t tid;

int sockfd = conct("192.168.1.112", 60000);

if (sockfd == -1) {

return -1;

}

while (1) {

connfd = accept(sockfd, NULL, NULL);

if (connfd == -1) {

return -1;

}

pthread_create(&tid, NULL, doSth, &connfd);

pthread_detach(tid);

}

return 0;

}

在这个示例中:

  • `pthread_create` 用于创建新的线程来处理客户端请求。

  • `pthread_detach` 用于分离线程,使其在完成后自动回收资源。

3.3 IO多路复用

IO多路复用技术允许单个进程/线程处理多个IO操作,常用于高并发场景。主要实现方式有:

  • select:检查多个文件描述符的状态,判断是否可以进行读写操作。

  • poll:与`select`类似,但支持更多的文件描述符。

  • epoll:高效的IO多路复用机制,适用于大规模文件描述符的场景。

四、IO模型

4.1 阻塞IO

在阻塞IO模型中,系统调用会阻塞直到有数据可用或操作完成。例如,`fgets`、`scanf`、`read`、`recv`等。

特点:

  • CPU占有率低:由于阻塞等待,CPU不会频繁进行上下文切换。

  • 执行效率低:处理效率低下,特别是在处理大量连接时。

4.2 非阻塞IO

非阻塞IO模型允许系统调用立即返回,无论是否有数据可用。需要通过轮询来检查数据的到达。

特点:

  • CPU占有率高:由于轮询机制,CPU会不断检查IO状态,导致较高的占用率。

  • 实现复杂:需要处理数据是否可用的逻辑。

实现步骤:

  1. 获取文件描述符的属性。

  2. 增加非阻塞属性。

  3. 设置新属性。

示例代码:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <string.h>

#include <signal.h>

void handle(int signo) {

char buf[1024] = {0};

fgets(buf, sizeof(buf), stdin);

printf("STDIN : %s\n", buf);

}

int main(int argc, char *argv[]) {

signal(SIGIO, handle);

char buf[1024] = {0};

mkfifo("./fifo", 0666);

int fd = open("./fifo", O_RDONLY);

int flag = fcntl(0, F_GETFL);

flag = flag | O_ASYNC;

fcntl(0, F_SETFL, flag);

fcntl(0, F_SETOWN, getpid());

while (1) {

memset(buf, 0, sizeof(buf));

read(fd, buf, sizeof(buf));

sleep(1);

printf("%s\n", buf);

}

close(fd);

return 0;

}

4.3 信号驱动IO

信号驱动IO模型通过信号机制来通知数据的到达。可以减少CPU的占用率,因为系统会在数据到达时发送信号。

特点:

  • 异步通知:当IO操作准备好时,系统会发送信号通知进程。

  • 效率高:适合处理少量IO操作的场景。

实现步骤:

  1. 增加异步属性 `O_ASYNC`。

  2. 关联信号和当前进程。

  3. 注册信号处理函数。

相关推荐
久绊A25 分钟前
网络信息系统的整个生命周期
网络
_PowerShell30 分钟前
[ DOS 命令基础 3 ] DOS 命令详解-文件操作相关命令
网络·dos命令入门到精通·dos命令基础·dos命令之文件操作命令详解·文件复制命令详解·文件对比命令详解·文件删除命令详解·文件查找命令详解
_.Switch3 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
qq_254674413 小时前
工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置
网络
JokerSZ.3 小时前
【基于LSM的ELF文件安全模块设计】参考
运维·网络·安全
小松学前端6 小时前
第六章 7.0 LinkList
java·开发语言·网络
城南vision6 小时前
计算机网络——TCP篇
网络·tcp/ip·计算机网络
Ciderw6 小时前
块存储、文件存储和对象存储详细介绍
网络·数据库·nvme·对象存储·存储·块存储·文件存储
Tony聊跨境7 小时前
独立站SEO类型及优化:来检查这些方面你有没有落下
网络·人工智能·tcp/ip·ip