多进程并发服务器
文章目录
- 思路
- 问题
- 多进程并发回环服务器代码
- 客户端代码
思路
每当一个客户端连接服务器后,创建一个子进程负责与该客户端通信,客户端断开连接之后,服务器回收子进程资源。
问题
问题1:父进程阻塞在等待连接(
accept())处,不能在父进程回收资源,可以使用信号SIGCHLD进行软中断回调处理,当子进程结束后会产生SIGCHLD信号,信号触发回调函数,进程子进程资源回收,父进程阻塞在accept()函数时遇到软中断就会产生EINTR错误信号,这就需要处理accept函数返回值为-1时的错误,判断错误号errno,若errno == EINTR则继续等待客户端连接进入accept阻塞。
问题2:由于多个进程同时退出时也仅有一个
SIGCHLD信号,所以在有SIGCHLD信号时,回调函数内就要循环执行释放子进程资源,直到子进程资源释放完成。
信号的注册,以及回调函数的编写:
//子进程回收回调函数
void recvChild(int arg)
{while(1){int ret = waitpid(-1, NULL, WNOHANG);if(ret > 0){printf("recv child, the num is:%d\n", ret);}else if(ret == 0){//还有子进程}else if(ret == -1){//没有子进程了break;}}
}//注册信号,解决子进程的回收问题struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = recvChild;sigaction(SIGCHLD, &act, NULL);
问题3:在使用客户端发送数据的时候,是先使用
write发送数据,然后通过read读取数据,该读取是阻塞的,所以一开始没有数据时是一直阻塞的,回环服务器接收到数据回传给客户端,这样客户端和服务器同时进行read时,就会出现都阻塞的状态。
可以设置客户端先发送,再读取,客户端发送后,数据经过服务器回传,客户端收到数据后,再进行下一次发送,若有一次数据丢失则无法进行数据发送,有一直阻塞在接收的风险。
也可以在客户端设置两个进程,一个发送进程,一个接收进程,这样就可以解决。
问题4:接收数据中没有结束符’\0’,在`printf %s时,会导致数据错误(数据先长后短,打印的会包含上次数据),注意结束符的位置,strlen计算到结束符之前。
通过在接收的字符串后补上结束符处理
或者接收数据前对接收数组进行清空处理
********////接收数据没有字符结束符,无法判断数据结束,//使用printf%s出现问题:可以将末尾增加字符结束符/0,也可以使用数据初始化(浪费资源)
//memset(recv, 0, 1024);
int len = read(cfd, recv, 1024);
recv[len] = 0;
多进程并发回环服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>void recvChild(int arg)
{while(1){int ret = waitpid(-1, NULL, WNOHANG);if(ret > 0){printf("recv child, the num is:%d\n", ret);}else if(ret == 0){//还有子进程}else if(ret == -1){//没有子进程了break;}}
}int main()
{//注册信号,解决子进程的回收问题struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = recvChild;sigaction(SIGCHLD, &act, NULL);//socketint lfd = socket(PF_INET, SOCK_STREAM, 0);if(lfd == -1){perror("socket");exit(-1);}//bindstruct sockaddr_in saddr;saddr.sin_family = AF_INET;inet_pton(AF_INET, "192.168.1.108", &saddr.sin_addr.s_addr);//saddr.sin_addr.s_addr = INADDR_ANY;saddr.sin_port = htons(9999);int ret = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1){perror("bind");exit(-1);}//listenret = listen(lfd, 2);if(ret == -1){perror("listen");exit(-1);}int prosess_num = 0;while(1){//acceptstruct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd, (struct sockaddr *)&caddr, &len);if(cfd == -1){if(errno == EINTR) continue;perror("accept");exit(-1);}//childprosess_num++;pid_t fd = fork();if(fd == -1){perror("fork");exit(-1);}if(fd == 0){char cip[16];printf("the process %d link success!\n", prosess_num);inet_ntop(AF_INET, &caddr.sin_addr, cip, sizeof(cip));printf("client IP:%s, Port:%d\n\n", cip, ntohs(caddr.sin_port));char recv[1025];while(1){********//
//接收数据没有字符结束符,无法判断数据结束,
//使用printf%s出现问题:可以将末尾增加字符结束符/0,也可以使用数据初始化(浪费资源)//memset(recv, 0, 1024);int len = read(cfd, recv, 1024);recv[len] = 0;if(len == -1){perror("read");exit(-1);}else if(len > 0){if(strcmp(recv, "break\r\n") == 0) break;write(cfd, recv, len+1);printf("IP:%s Port:%d: %s", cip, ntohs(caddr.sin_port), recv);}else{printf("client is closed...\n");break;}}printf("the process %d, IP:%s, port:%d, will close!\n", prosess_num, cip, ntohs(caddr.sin_port));close(cfd);exit(0);}}close(lfd); return 0;
}
客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>int main()
{int lfd = socket(PF_INET, SOCK_STREAM, 0);if(lfd == -1){perror("socket");exit(-1);}struct sockaddr_in saddr;saddr.sin_family = AF_INET;int len = sizeof(saddr);inet_pton(AF_INET, "192.168.1.108", &saddr.sin_addr.s_addr);saddr.sin_port = htons(9999);int ret = connect(lfd, (struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1){perror("connect");exit(-1);}printf("client link success!\n");//由于读操作会阻塞,客户端需要先发送数据,若先读取数据,一个进程就会阻塞住,一个进程就要先发数据,如果一次数据没有接收到,则会阻塞住。//可以采用两个进程,发、收互不影响pid_t pid = fork();if(pid==0){char rbuf[1024];while(1){//memset(rbuf, 0, 1024);int lent = read(lfd, rbuf, 1024);if(lent > 0){printf("send: %s", rbuf);}else if(lent == -1) perror("read");}}else if(pid > 0){int i = 0;char sbuf[1024];while(1){ i++;if(i > 255) i = 0;sprintf(sbuf, "the num is %d\n", i);write(lfd, sbuf,strlen(sbuf));sleep(1);}}close(lfd);return 0;
}
相关文章:
多进程并发服务器
文章目录 思路问题多进程并发回环服务器代码客户端代码 思路 每当一个客户端连接服务器后,创建一个子进程负责与该客户端通信,客户端断开连接之后,服务器回收子进程资源。 问题 问题1:父进程阻塞在等待连接(accept())处…...
2021秋招总结
2021 秋招总结 作为星球第一批准备秋招的人,经过这几个月的面试之后,感觉也算是有一些小小的经验了吧,就做一个简单的记录,希望能够为星球中准备秋招的伙伴们提供一些参考吧~ 序 4月初加入星球,到9月底,一…...
Linux6.34 Kubernetes yaml文件详解
文章目录 计算机系统5G云计算第三章 LINUX Kubernetes yaml文件详解一、yaml文件概述1.查看 api 资源版本标签2.写一个yaml文件demo 计算机系统 5G云计算 第三章 LINUX Kubernetes yaml文件详解 一、yaml文件概述 Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式…...
防火墙笔记
什么是防火墙 在计算机网络中是指设置在可信任的内部网络和不可信任的外部网络之间的屏障,通过强化边界控制保障内容安全,同时不妨碍内部对外部的访问。 20世纪80年代,最早的防火墙几乎与路由器同时出现,第一代防火墙主要基于包过…...
使用代码下载开源的大模型文件示例以及中文微调llama资源汇总:
一、下载示例 from huggingface_hub import snapshot_downloadrepo_id "THUDM/chatglm2-6b" local_dir ./chatglm2-6b/ cache_dir local_dir "/cache" while True:try:snapshot_download(cache_dircache_dir,local_dirlocal_dir,repo_idrepo_id,loca…...
Wav2vec2 论文阅读看到的一些问题
Wav2vec2 论文阅读看到的一些问题 这里只是简单的思考一下论文的一些问题,不是论文解读。 Q1. 为什么wav2vec依旧需要Transformer来做推理,而不直接使用VQ生成的内容? A1. Transformer在更长的序列上有更好的编码效果,例如论文也写…...
爬虫学习记录(持续更新)
一、问题记录 1.使用webdriver报错AttributeError: str object has no attribute capabilities 解决:目前使用的selenium版本是4.11.2,可以不必设置driver.exe的路径,selenium可以自己处理浏览器和驱动程序,因此,使用…...
libevent源码学习1---创建event
libevent源码学习1—创建event Libevent是一个用于开发可扩展性网络服务器的基于事件驱动(event-driven)模型的非阻塞网络库。安装请参考ubuntu下载安装libevent event_base 使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个 event_base 结构体持有一个…...
Python类的设计
Python类的设计 # 定义一个闹钟类 class Clock:__cureen_keyNone # 私有成员不能改变和使用def __init__(self, id, price): # 类对象是立即自动执行self.id idself.price pricedef ring(self):import winsound # 内置声音方法winsound.Beep(2000,3000)clock1 Clock(…...
微信小程序的项目解构
视频链接 黑马程序员前端微信小程序开发教程,微信小程序从基础到发布全流程_企业级商城实战(含uni-app项目多端部署)_哔哩哔哩_bilibili 接口文档 https://www.escook.cn/docs-uni-shop/mds/1.start.html 1:微信小程序宿主环境 1:常见的宿…...
【Archaius技术专题】「Netflix原生态」动态化配置服务之微服务配置组件变色龙
前提介绍 如果要设计开发一套微服务基础架构,参数化配置是一个非常重要的点,而Netflix也开源了一个叫变色龙Archaius的配置中心客户端,而且Archaius可以说是比其他客户端具备更多生产级特性,也更灵活。*在NetflixOSS微服务技术栈…...
python条件分支和循环语句
python中没有{}的写法,一般时通过缩进的方式来确定分支和循环需要执行的代码块。 if 需要判断的条件表达式:条件成立时的动作 elif 需要判断的条件表达式:条件成立时的动作 else:动作for 变量 in 迭代对象:动作 示例: while 退出条件:动作...
工具推荐:Wireshark网络协议分析工具(对比tcpdump)
文章首发地址 Wireshark是一款开源的网络协议分析工具,可以捕获网络数据包并对其进行详细的分析和解释。下面是Wireshark的详细介绍: Wireshark 工作原理 Wireshark通过捕获网络接口上的数据包,将其转换为可读的格式,并在界面…...
[OnWork.Tools]系列 04-快捷启动
简介 主要功能是将常用的软件拖动到软件中,实现快速点击启动,结合软件设置中的设置的快捷键,可以快速呼出对应的面板,使用快捷键快速启动应用 拖拽内容 拖拽快捷方式到面板,双击快速打开 拖拽文件方式到面板,双击快速打开 拖拽文件夹到面板双击快速打开 拖拽项目调整顺序 右…...
如何将项目挂后台运行?【nohup和tmux】
挂后台运行,防止霸屏。 线上的程序不会将日志输出到控制台,而是输出到日志文件,方便运维查阅信息。 一.nohup--挂后台运行的命令 //nohup--英文全称no hang up,可以后台运行指定命令 //hello.log是指将日志输出到hello.log文件 …...
什么是进程、线程、协程
什么是进程? 我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序则是具有某种功能的程序,程序…...
Python爬虫——selenium_访问元素信息
from selenium import webdriver# 创建浏览器对象 path files/chromedriver.exe browser webdriver.Chrome(path)# 访问地址 url https://www.baidu.com browser.get(url)input browser.find_element_by_id(su)获取元素属性 .get_attribute(class)print(input.get_attribu…...
Linux 文件基本属性
Linux 文件基本属性 Linux 系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限。 为了保护系统的安全性,Linux 系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定。 在 Linux 中我…...
CSS 盒模型是什么?它包含哪些属性?标准盒模型/怪异盒模型
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 盒模型⭐ 标准盒模型⭐ 怪异盒模型⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感…...
VB+SQL光盘信息管理系统设计与实现
摘 要 我的毕业设计课题为“光盘管理系统”,该系统完成光盘相关信息的输入、保存和维护、是按照方便用户、容易操作、确保数据一致完整的原则进行设计。这次毕业设计的开发工具是Visual Basic 6.0,操作平台是Windows2000 Professional中文版,选用的数据库后台是SQL server2…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
