深入了解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. 注册信号处理函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/53201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NetCore发布到IIS

一&#xff1a;安装sdk(下载 .NET 8.0 SDK (v8.0.302) - Windows x64 Installer) 与donet Runtime(.NET Downloads (Linux, macOS, and Windows))选择对应的版本下载 二&#xff1a;解决问题&#xff1a;HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面&#x…

【C++11(一)之入门基础)】

文章目录 C简介统一的列表初始化&#xff5b;&#xff5d;初始化 std::initializer_liststd::initializer_list是什么类型&#xff1a;std::initializer_list使用场景&#xff1a; 声明autodecltypenullptr STL中一些变化 C简介 在2003年C标准委员会曾经提交了一份技术勘误表(…

大数据新视界--大数据大厂之MySQL 数据库课程设计:数据安全深度剖析与未来展望

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

一种误差较小的轮廓面积计算算法

1.背景 基于微分思想的轮廓面积计算方法之一是将多边形轮廓边与X轴会Y轴进行围合&#xff0c;形成一个个梯形&#xff0c;每个梯形的面积有符号&#xff0c;累计求和即得到多边形轮廓的面积。详见博主之前的文章&#xff0c; 记录导致计算轮廓面积出错的一个坑点-CSDN博客文章…

C++ Qt进程间通信机制之QRO、QRemoteObjectHost

文章目录 QRO_serverQRO_client深入浅出C++ Qt开发技术专栏:https://blog.csdn.net/yao_hou/category_9276099.html Qt高级开发视频教程 https://edu.csdn.net/course/detail/37447?spm=1001.2014.3001.5507 C++零基础入门视频教程 https://edu.csdn.net/course/detail/379…

Rust 学习笔记 3:一般性编程概念

上一篇&#xff1a;Rust 学习笔记 2&#xff1a;猜数字游戏 文章目录 1. 前言2. 背景3. Rust 中的一般性编程概念3.1 变量及其可变性(Mutability)3.1.1 变量定义3.1.2 常量3.1.3 变量隐藏(Shadowing) 3.2 基本类型3.2.1 标量(scalar)类型3.2.1.1 整型(Integer Types)3.2.1.2 浮…

项目拆解:短视频冷门赛道—ai绘画+温馨小屋,引流变现全攻略

在这个快节奏的时代&#xff0c;工作、学习、家庭的重担仿佛三座大山&#xff0c;让人喘不过气&#xff0c;心情时常跌入谷底。就像蜗牛遇到威胁会缩进壳里&#xff0c;我们也会在疲惫和忧虑时&#xff0c;渴望一个属于自己的温暖小窝&#xff0c;来安放疲惫的心灵。而自媒体平…

Flink 1.14.* Flink窗口创建和窗口计算源码

解析Flink如何创建的窗口&#xff0c;和以聚合函数为例&#xff0c;窗口如何计算聚合函数 一、构建不同窗口的build类1、全局窗口2、创建按键分流后的窗口 二、在使用窗口处理数据流时&#xff0c;不同窗口创建的都是窗口算子WindowOperator1、聚合函数实现2、创建全局窗口(入参…

SpringFrameWork学习笔记

本笔记基于【尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发】https://www.bilibili.com/video/BV1AP411s7D7?vd_sourcea91dafe0f846ad7bd19625e392cf76d8 总结 资料获取网址&#xff1a;https://www.wolai.com/v5Kuct5ZtPeVBk4NBUGBWF 技术…

Java项目: 基于SpringBoot+mysql房产销售系统 (含源码+数据库+开题报告+答辩PPT+毕业论文)

一、项目简介 本项目是一套基于SpringBootmysql房产销售系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能齐…

数学基础 -- 线性代数之LU分解

LU分解 LU分解&#xff08;LU Decomposition&#xff09;是线性代数中非常重要的一种矩阵分解方法。它将一个方阵分解为一个下三角矩阵&#xff08;L矩阵&#xff09;和一个上三角矩阵&#xff08;U矩阵&#xff09;的乘积。在数值线性代数中&#xff0c;LU分解广泛用于求解线…

Halcon基于灰度值的模板匹配

Halcon基于灰度值的模板匹配 基于灰度值的模板匹配是最经典的模板匹配算法&#xff0c;也是最早提出来的模板匹配算法。这种算法的根本思想是&#xff0c;计算模板图像与检测图像之间的像素灰度差值的绝对值总和&#xff08;SAD方法&#xff09;或者平方差总和&#xff08;SSD…

Spring解析

目录 容器与 bean 1) 容器接口 演示1 - BeanFactory 与 ApplicationContext 的区别 代码参考 收获&#x1f4a1; 演示2 - 国际化 2) 容器实现 演示1 - DefaultListableBeanFactory 代码参考 收获&#x1f4a1; 演示2 - 常见 ApplicationContext 实现 代码参考 收获…

ico格式怎么转换?5个软件让你轻松转换文件格式

ico格式怎么转换&#xff1f;5个软件让你轻松转换文件格式 ICO格式是常用于网站图标和应用程序图标的文件格式&#xff0c;虽然它很常见&#xff0c;但并非所有图像编辑软件都支持直接保存为ICO格式。如果你需要将其他格式的图片&#xff08;如PNG、JPG等&#xff09;转换为IC…

读书学习笔记入门 # Datawhale X 李宏毅苹果书 AI夏令营

文章目录 学习目标&#xff1a;学习内容&#xff1a;Task 1 通过案例了解机器学习机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09;和深度学习&#xff08;Deep Learning&#xff0c;DL&#xff09;的基本概念什么是回归&#xff08;regression&#xff09;什么…

深入解析Linux轻量级进程:线程的概念、原理、优缺点及其与进程的关系与区别

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f4da;Linux线程&#x1f4d5;什么是线程*可以使用多进程去并发的执行一个进程的代码&#xff0c;那为什么要由线程呢&#x…

基于CloudflareSpeedTest项目实现git clone加速

1.网络测速 「自选优选 IP」测试 Cloudflare CDN 延迟和速度&#xff0c;获取最快 IP 更多内容参考项目&#xff1a;https://github.com/XIU2/CloudflareSpeedTest 国外很多网站都在使用 Cloudflare CDN&#xff0c;但分配给中国内地访客的 IP 并不友好&#xff08;延迟高、丢…

Pixelmator Pro for Mac 专业图像处理软件【媲美PS的修图软件】

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

【STM32+HAL库】---- 通用定时器输入捕获PWM信号

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟RCC 1.2 配置定时器 1.2.1 配置输入捕获 选择通用定时器TIM2-Channel 1为输入捕获引脚&#xff0c;对应IO口是PA0,时钟源选择内部时钟源Internal clock,工作模…

Unity实战案例 2D小游戏HappyGlass(模拟水珠)

本案例素材和教程都来自Siki学院&#xff0c;十分感谢教程中的老师 本文仅作学习笔记分享交流&#xff0c;不作任何商业用途 预制体 在这个小案例中&#xff0c;水可以做成圆形但是带碰撞体&#xff0c;碰撞体比图形小一圈&#xff0c;顺便加上Trail renderer组件 材质 将碰撞…