Linux socket编程(二):多进程服务器

news2024/10/6 20:38:12

一、多进程服务器

最简单的的服务器程序执行流程为:创建socket → \rightarrow 绑定监听的IP地址和端口 → \rightarrow 监听客户端连接 → \rightarrow 接受/发送数据。当服务端调用read阻塞等待一个客户端发来数据时,无法同时响应其它客户端的连接请求,无法接受其它客户端发来的数据。要想同时与多个客户端建立连接并处理请求,可以为每个连接的客户端创建一个子进程,在子进程中接受/发送客户端的数据,各个子进程之间互不干扰。

按照《Unix网络编程》中所述,多进程服务端程序的逻辑为:
多进程服务器端程序
主进程只负责Accept客户端连接,将得到的文件描述符交给子进程处理,自己不需要处理。需要注意两点:
父进程中关闭connfd,子进程中关闭listenfd: 每个文件的file_struct中保存了这个文件的引用计数,即有多少个进程持有这个文件的文件描述符,每次close(fd)将文件的引用计数-1,只有当引用计数 == 0时才真正关闭文件。子进程复制父进程的资源,因此fork()创建子进程时复制了connfd和listenfd,这两个socket文件的引用计数+1,在子进程中不需要listenfd,直接关闭,这个操作不会影响父进程中的listenfd,因为这时listenfd对应的socket文件的引用计数继续保持为1,socket不会关闭。同理,父进程中也不需要connfd,可以直接关闭。

子进程执行完成时调用eixt(0): 子进程执行的代码和父进程是一样的,并不是只会执行if((pid=fork()) == 0)后面这部分。因此子进程完成后显示调用exit(0)让子进程推出,否则子进程还会回到Accept这条语句上,这不是子进程需要做的。

以上流程写成代码就是:

// 子进程执行的函数
void client_handler(int clientfd, int sockfd, unsigned short port) {
    close(sockfd);
    char buffer[1024];
    int ret = 0;
    while (true) {
        memset(buffer, 0, sizeof(buffer));
        printf("receive message from port: %d\t", port);
        if (!receive_message(clientfd, buffer)) {
            break;
        }
    }
    printf("exit child process\n");
}

int main() {
    signal(SIGCHLD, SIG_IGN);
    int sockfd = open_socket();
    int clientfd = 0;
    struct sockaddr_in client_addr;
    int size = sizeof(struct sockaddr);
    while (true) {
        clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (socklen_t*)&size);
        if (fork() > 0) {
            close(clientfd);
            continue;
        } else {
            client_handler(clientfd, sockfd, client_addr.sin_port);
            exit(0);
        }
    }
    close(sockfd);
    return 0;
}

为什么要signal(SIGCHLD,SIG_IGN): 子进程退出时,会给父进程发送SIGCHLD信号,如果我们没有指定父进程对于SIGCHLD信号的处理函数,会执行默认的处理方式——SIG_DFL,这种处理方式是不处理这个信号(注意:不处理信号不等于丢弃信号),子进程的PCB(task_struct)不会被清理,变为僵尸进程。我们指定signal(SIGCHLD, SIG_IGN)后,代表父进程丢弃SIGCHLD信号,让系统内核负责子进程的销毁。

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

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

相关文章

七、CANdelaStudio入门-Variant概念与应用

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的Variant概念与应用,欢迎各位朋友订阅、…

Redis实现互相关注功能

Redis实现互相关注功能 我们要实现关注功能,首先,我们需要得到关注的目标ID: PutMapping("/{id}/{isFollow}")public Result followUser(PathVariable("id") Long id,PathVariable("isFollow") Boolean isFol…

下一代大数据分布式存储技术Apache Ozone初步研究

文章目录 概述定义特性架构总体架构写数据读数据 部署安装方式安装Docker启动Docker-compose启动企业预置型(On Premise)安装 实践命令行接口Ofs (Hadoop兼容)Recon API 概述 定义 Apache Ozone 官网地址 https://ozone.apache.org/ 最新版本1.3.0 Apache Ozone 官网最新文档地…

Java线程间通信方式(2)

前文了解了线程通信方式中的Object.wait/Object.notify以及Semaphore,接下来我们继续了解其他的线程间通信方式。 CountDownLatch CountDownLatch利用一个指定的计数初始化,由于调用了countDown方法,await方法会阻塞直到当前技术为0,之后所…

PHP-8.2.5+IIS10 php-cgi.exe - FastCGI 进程意外退出

服务器信息: Windows Server 2019 Standard. Internet Information Services(Version 10.0.17763.1) PHP版本: PHP Version 8.2.5 php-8.2.5-nts-Win32-vs16-x64 下载地址:https://windows.php.net/download#php-8.2 错误信息: H…

【网络】-- UDP协议

目录 传输层 再谈端口号 端口号范围划分 认识知名端口号(Well-Know Port Number) 两个问题 netstat pidof UDP协议 UDP的特点 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 传输层 负责数据能够从发送端传输接收端。 再谈端口号 端…

【ROS】ubuntu18.04安装ROS(ROS1 Melodic)

1、添加中科大ROS源 1.1、添加源 sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ lsb_release -cs main" > /etc/apt/sources.list.d/ros-latest.list1. 2、添加公钥 sudo apt-key adv --keyserver hkp://keyser…

输入捕获实验

实验内容 用TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电平的脉宽(用 WK_UP 按键输入高电平),通过串口打印高电平脉宽时间。 输入捕获简介 输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的…

新库上线 | 全国工艺美术大师信息数据

全国工艺美术大师信息数据 一、数据简介 作为物质产品,工艺美术反映着一定时代、一定社会的物质的和文化的生产水平;作为精神产品,它的视觉形象(造型、色彩、装饰)又体现了一定时代的审美观。我国工艺美术品的制作较早…

java基础+注解笔记【狂神说java】

基础部分–总结 基础包的命名 //一般为域名倒置 page com.yang.base基础语法 类和方法 根据不同的写法–大小写的差异可以判别是类对象还是方法名 类的首字母都要大写,方法首字母小写可以理解为,类对象是class,方法是函数 类对象 方法 使…

浅谈在 Vue2 和 Vue3 中计算属性和侦听器的一些变化

文章目录 📋前言🎯计算属性🎯侦听器📝最后 📋前言 计算属性 computed 和侦听器 watch 都是 Vue.js 框架中用来响应式更新视图的重要概念。因此无论是在哪个版本,它们都是不可缺少的概念,这篇文…

音视频八股文(5)--SDL音视频渲染实战。会使用就行,不需要深究。

01-SDL子系统 SDL将功能分成下列数个子系统(subsystem): ◼ SDL_INIT_TIMER:定时器 ◼ SDL_INIT_AUDIO:音频 ◼ SDL_INIT_VIDEO:视频 ◼ SDL_INIT_JOYSTICK:摇杆 ◼ SDL_INIT_HAPTIC&#xff1…

第十三章 享元模式

文章目录 前言一、享元模式基本介绍二、享元模式解决网站展现项目完整代码WebSite 抽象网站类User 外部状态用户内部状态网站 ConcreteWebSite网站工厂产生网站和负责共享(池) WebSiteFactoryClint 测试 三、享元模式在JDK-Interger的应用源码分析四、享…

ERBuilder Data Modeler Crack

ERBuilder Data Modeler Crack 为过程、视图和触发器添加了人工智能驱动的描述生成。 添加了一种新的自动排列方法,可以轻松地排列和组织表格,从而简化ER图的可视化显示。 添加了使用两种身份验证方法创建到远程服务器的SSH连接的功能:密码身…

Linux - 第10节 - Linux多线程(二)

1.Linux线程同步 1.1.同步概念与竞态条件 线程互斥的设计是正确的,但线程互斥在某些场景下并不合理,有可能导致饥饿问题。 饥饿问题:某个执行流访问完临界资源后释放锁,此时相较于其他执行流,该执行流离锁更近&#x…

【目标检测论文阅读笔记】Detection of plane in remote sensing images using super-resolution

Abstract 由于大量的小目标、实例级噪声和云遮挡等因素,遥感图像的目标检测精度低,漏检率或误检率高。本文提出了一种新的基于SRGAN和YOLOV3的目标检测模型,称为SR-YOLO。解决了SRGAN网络 对超参数的敏感性和模态崩溃问题。同时,Y…

【中级软件设计师】—(针对上午题)算法分析与设计(三十八)

【中级软件设计师】—(针对上午题)算法分析与设计(三十八) 一、回溯法 1. 什么是回溯法? 相信"迷宫"是许多人儿时的回忆,大家小时候一定都玩过迷宫游戏。我们从不用别人教,都知道走…

TryHackMe-M4tr1x: Exit Denied(boot2root)

M4tr1x: Exit Denied 大多数人只看到一个完美构建的系统。但你一直都是不同的。你不仅看到表面上的东西,还看到 它下面有什么统治;调节和调节的内部关联机制 几乎完美地管理其每个模块,以至于它试图隐藏所有模块 其多面设计中的微小孔。但是&#xff0c…

【数据结构】链表详解

本片要分享的内容是链表,为方便阅读以下为本片目录 目录 1.顺序表的问题及思考 1.链表的遍历 2.头部插入 2.1开辟空间函数分装 3.尾部插入 纠正 4.尾部删除 5.头部删除 6.数据查找 7.任意位置插入 1.顺序表的问题及思考 上一篇中讲解了顺序表中增删查…

【Linux】如何理解缓冲区

文章目录 &#x1f4d5; 看现象&#x1f4d5; 理解本质&#x1f4d5; 模拟文件接口mystdio.hmystdio.c &#x1f4d5; 看现象 如下代码&#xff0c;运行结果如图。 1 #include<sys/types.h> 2 #include<sys/stat.h> 3 #include<fcntl.h> 4 #include<s…