多进程并发服务器
文章目录
- 思路
- 问题
- 多进程并发回环服务器代码
- 客户端代码
思路
每当一个客户端连接服务器后,创建一个子进程负责与该客户端通信,客户端断开连接之后,服务器回收子进程资源。
问题
问题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…...
Stable-Diffusion-v1-5-archiveWebUI插件开发指南:Python扩展接口与SDK文档
Stable-Diffusion-v1-5-archive WebUI插件开发指南:Python扩展接口与SDK文档 1. 引言:为什么需要开发自己的WebUI插件? 如果你已经用了一段时间的Stable Diffusion v1.5 Archive,可能会发现一个痛点:每次生成图片都要…...
SAP财务数据一致性检查:手把手教你用ABAP程序自动修复ACDOCA表异常
SAP财务数据一致性检查:手把手教你用ABAP程序自动修复ACDOCA表异常 在SAP财务模块的日常运维中,ACDOCA表作为新总账(New GL)的核心表,承载着所有财务凭证的明细数据。然而在实际操作中,我们经常会遇到ACDOCA表与BSEG表数据不一致的…...
手把手教你用XML为RimWorld Mod添加第一个新物品:从Defs文件到游戏内生效全流程
从零开始为RimWorld Mod添加自定义武器:XML实战指南 第一次打开RimWorld的Mod文件夹时,那些密密麻麻的XML文件可能让人望而生畏。但别担心——每个资深Mod作者都经历过这个阶段。今天我们就用最直观的方式,带你完成第一个可运行的物品Mod&…...
Qwen2.5-VL-7B-Instruct部署教程:离线环境无网络安装依赖包完整方案
Qwen2.5-VL-7B-Instruct部署教程:离线环境无网络安装依赖包完整方案 1. 学习目标与前置准备 Qwen2.5-VL-7B-Instruct是一款强大的多模态视觉-语言模型,能够同时处理图像和文本输入,生成高质量的响应。本教程将带你完成在离线环境下的完整部…...
文墨共鸣大模型Dify平台无缝集成:可视化构建AI文本处理应用
文墨共鸣大模型Dify平台无缝集成:可视化构建AI文本处理应用 你是不是也遇到过这样的场景:手头有一个很棒的AI大模型,比如文墨共鸣,但每次想用它做点事情,都得写代码、调接口,过程繁琐,门槛不低…...
YOLOv12与MATLAB联合仿真:算法原型快速验证与性能分析
YOLOv12与MATLAB联合仿真:算法原型快速验证与性能分析 对于习惯在MATLAB环境中工作的算法工程师和研究人员来说,一个常见的痛点在于:当需要验证前沿的深度学习目标检测算法(如最新的YOLOv12)时,往往不得不…...
Ubuntu 22.04 网络配置疑难:为何 netplan apply 后 IP 仍“顽固”不变?
1. 当netplan apply失效时,我们到底遇到了什么? 最近在帮朋友调试一台Ubuntu 22.04服务器时,遇到了一个特别"顽固"的问题:明明用netplan修改了IP地址,执行netplan apply也没报错,但重启后IP地址就…...
SmallThinker-3B-Preview多轮对话效果实测:技术方案讨论与迭代
SmallThinker-3B-Preview多轮对话效果实测:一次关于高并发秒杀系统的技术方案迭代 最近在测试一些轻量级的对话模型,想看看它们在处理复杂技术问题时的实际表现。我手头正好有一个叫SmallThinker-3B-Preview的模型,虽然参数规模不大…...
Qwen3-14B-Int4-AWQ效果深度评测:代码生成、推理与数学能力横向对比
Qwen3-14B-Int4-AWQ效果深度评测:代码生成、推理与数学能力横向对比 1. 评测背景与模型特点 Qwen3-14B-Int4-AWQ作为通义千问系列的最新量化版本,在保持原版14B参数规模的同时,通过AWQ(Activation-aware Weight Quantization&am…...
FLUX.1-dev实战应用:5个创意场景,让你的设计效率翻倍
FLUX.1-dev实战应用:5个创意场景,让你的设计效率翻倍 你是不是也遇到过这样的困境?脑子里有一个绝妙的创意画面,却苦于找不到合适的素材,或者请设计师制作周期长、成本高。又或者,面对社交媒体日更的压力&…...
