C/S架构学习之多进程实现TCP并发服务器
- 多进程实现TCP并发服务器的实现流程:
- 一、自定义信号处理函数(sig_func函数):
void sig_func(int signum){wait(NULL);}
- wait函数:
#include <sys/types.h>#include <sys/wait.h>pid_t wait(int *wstatus);/*功能:wait函数是在父进程中使用,用来回收子进程的资源。这个函数会阻塞等待任意一个子进程退出。子进程在退出的时候exit的参数可以被父进程接收到。参数:wstatus:用来获取子进程退出的信息的。如果不关心子进程退出的状态,可以传NULL如果关心子进程退出的状态,可以传一个int类型变量的地址。0-6 :7个bit位表示终止子进程的信号的编号8-15:8个bit位表示子进程退出的状态WIFEXITED(wstatus) 为true 说明子进程是正常结束WEXITSTATUS(wstatus) 如果子进程是正常的退出的 使用这个宏可以获取子进程退出的值WIFSIGNALED(wstatus) 为true 说明子进程是被信号中断的WTERMSIG(wstatus) 如果子进程是被信号中断的 使用这个宏可以获取终止子进程的信号的编号返回值:成功 返回退出的子进程的pid失败 -1 重置错误码 */
- 二、创建套接字(socket函数):
- 通信域选择IPV4网络协议、套接字类型选择流式;
int sockfd = socket(AF_INET,SOCK_STREAM,0); //通信域选择IPV4、套接字类型选择流式
- 三、填充服务器的网络信息结构体:
- 1.定义网络信息结构体变量;
- 2.求出结构体变量的内存空间大小;
- 3.结构体清零;
- 4.使用IPV4网络协议;
- 5.在终端输入的IP地址,即
inet_addr(argv[1]); - 6.在终端输入的网络字节序的端口号,即
htons(atoi(argv[2]));
struct sockaddr_in serveraddr; //定义网络信息结构体变量socklen_t serveraddrlen = sizeof(serveraddr);//求出结构体变量的内存空间大小memset(&serveraddr,0,serveraddrlen); //结构体清零serveraddr.sin_family = AF_INET; //使用IPV4网络协议serveraddr.sin_addr.s_addr = inet_addr(argv[1]); //IP地址serveraddr.sin_port = htons(atoi(argv[2]));//网络字节序的端口号
- 四、套接字和服务器的网络信息结构体进行绑定(bind函数):
int ret = bind(sockfd,(struct sockaddr *)&serveraddr,serveraddrlen);
- 五、套接字设置成被动监听(listen函数):
int ret1 = listen(sockfd, 5);
- 六、定义网络信息结构体变量保存来自客户端的消息(clientaddr):
struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);
- 七、注册信号处理函数回收资源( signal函数):
signal(SIGUSR1,sig_func);
- signal函数:
// SIGUSR1、SIGUSR2:// 该信号保留给用户程序使用// 默认操作:终止#include <signal.h>typedef void (*sighandler_t)(int);//给函数指针起别名sighandler_t signal(int signum, sighandler_t handler);/*功能:在进程中注册信号处理函数参数:signum:信号的编号(除了 SIGKILL 和 SIGSTOP之外的)handler:信号处理方式忽略: SIG_IGN默认: SIG_DFL捕捉: 自定义信号处理函数void sig_func(int signum){//捕捉到信号后的处理逻辑}返回值:成功 返回指向handler的指针失败 SIG_ERR 重置错误码*/
- 八、阻塞等待客户端的连接(accept函数):
int acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len);
- 九、创建子进程(fork函数)用接收来自客户端的数据(recv函数)和给客户端发送应答消息(send函数),且双方通信结束后,给父进程发信号回收资源(kill函数):
if(-1 == (pid = fork())){perror("fork error");exit(-1);}else if(0 == pid){int nbytes = recv(acceptfd,buf,sizeof(buf),0);printf("客户端发来数据[%s]\n",buf);strcat(buf,"----k"); //组装应答消息int ret2 = send(acceptfd,buf,sizeof(buf),0);//给父进程发信号,回收资源kill(getppid(),SIGUSR1);}else if(0 < pid){//等待新的客户端连接close(accept_fd);}
- kill函数:
#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);/*功能:给指定pid的进程发信号参数:pid 进程号>0 给指定的pid发信号,常用的用法0 给同组的进程发信号-1 给所有有权限操作的进程发信号,init除外<-1 如-100,给进程组id为100的所有进程发信号sig 信号的编号返回值:成功 0失败 -1 重置错误码 */
- 十、关闭套接字(close函数):
close(sockfd);
- 综合应用实例代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>//自定义信号处理函数
void sig_func(int signum)
{wait(NULL);
}int main(int argc, char const *argv[])
{//入参合理性检查if(3 != argc){printf("Usage : %s <IP> <PORT>\n",argv[0]);exit(-1);}//创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("socket error");exit(-1);}//填充服务器网络信息结构体struct sockaddr_in serveraddr;socklen_t serveraddr_len = sizeof(serveraddr);memset(&serveraddr,0,serveraddr_len);serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//将套接字与服务器网络信息结构体绑定if(-1 == bind(sockfd,(struct sockaddr *)&serveraddr,serveraddr_len)){perror("bind error");exit(-1);}//将套接字设置成被监听状态if(-1 == listen(sockfd,5)){perror("listen error");exit(-1);}//定义结构体保存客户端信息struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);//注册信号处理函数回收资源signal(SIGUSR1,sig_func);//阻塞等待客户端连接int accept_fd = 0;char buf[128] = {0};pid_t pid = 0;int nbytes = 0;while(true){if(-1 == (accept_fd = accept(sockfd,(struct sockaddr*)&clientaddr,&clientaddr_len))){perror("accept error");exit(-1);}//创建进程if(-1 == (pid = fork())){perror("fork error");exit(-1);}else if(0 == pid){ //子进程//收发数据close(sockfd);printf("客户端[%s : %d]连接到服务器\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));//接收客户端数据,并作出应答while(true){memset(buf,0,sizeof(buf));//接收消息if(-1 == (nbytes = recv(accept_fd,buf,sizeof(buf),0))){perror("recv error");break;}else if(0 == nbytes){printf("客户端[%s : %d]断开了连接\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));break;}if(!strcmp(buf,"quit")){printf("客户端[%s : %d]退出了\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));break;}printf("客户端[%s : %d]发来消息[%s]\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),buf);//组装应答strcat(buf,"------k");//发送应答if(-1 == send(accept_fd,buf,sizeof(buf),0)){perror("send error");exit(-1);}}//关闭套接字close(accept_fd);//给父进程发信号,回收资源kill(getppid(),SIGUSR1);//退出子进程exit(0);}else if(0 < pid){//等待新的客户端连接close(accept_fd);}}//关闭套接字close(sockfd);return 0;
}
- 本示例代码,仅供参考;
相关文章:
C/S架构学习之多进程实现TCP并发服务器
多进程实现TCP并发服务器的实现流程:一、自定义信号处理函数(sig_func函数): void sig_func(int signum){wait(NULL);}wait函数: #include <sys/types.h>#include <sys/wait.h>pid_t wait(int *wstatus);/*功能&#…...
VSCode 快速移动光标至行尾
最近在用vscode进行C编程,经常需要把光标跳到行尾去添加符号。 手动到行尾太麻烦了。 一种快捷方式是:用键盘上的“END”快捷键。 但是用这个键也不是很方便,因为“end”键离主键盘区太远。 另一种便捷的方式是:给vscode设置自定义…...
ACP.复盘方法
复盘要怎么做的有水准,让领导满意,方式方法很重要。今天给你们安利5种复盘方法,保准你省事,领导还满意。 一、KPT复盘法 7月份年中一直在做和复盘相关的事,像公司的OKR复盘、年中战略规划,不过日常很多生…...
Springboot 订餐管理系统idea开发mysql数据库web结构java编程计算机网页源码maven项目
一、源码特点 springboot 订餐管理系统是一套完善的信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发),系统具有 完整的源代码和数据库&…...
判断当前Activity是否有DialogFragment显示
DialogFragment一种情况是在当前Activity上启动,一种情况是在Fragment上启动,判断当前fragmentManager上是否有,以及遍历判断子fragment上是否有,即可确定是否有DialogFragment展示。 使用方式: // supportFragmentMa…...
开发一个npm组件包(2)
通过vueelement 原来后台 开发npm包的时候 会遇到一下几个问题 入口文件变化为package/index 需要再配置打包方法 package.json下 "scripts": {"package": "vue-cli-service build --target lib ./src/package/index.js --name managerpage --dest…...
迅为RK3568开发板Scharr滤波器算子边缘检测
本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程\04_OpenCV 开发配套资料\33”目录下,如下图所示: 在 Sobel 算子算法函数中,如果设置 ksize-1 就会使用 3x3 的 Scharr 滤波器。Scharr 算子是 Soble 算子在 ksize…...
HJ86 求最大连续bit数
目录 一、题目 二、代码 一、题目 求最大连续bit数_牛客题霸_牛客网 二、代码 #include <iostream> #include<stack> #include<vector> using namespace std; void TEN_to_TWO(int x, vector<int>& data) { //10进制转换成二进制stack<int&…...
Grafana 10 新特性解读:体验与协作全面提升
作者:徽泠(苏墨馨) 为了庆祝 Grafana 的 10 年里程碑,Grafana Labs 推出了 Grafana 10,这个具有纪念意义的版本强调增强用户体验,使各种开发人员更容易使用。Grafana v10.0.x 为开发者与企业展示卓越的新功能、可视化与协作能力&…...
Django实现音乐网站 ⒆
使用Python Django框架做一个音乐网站, 本篇主要为排行榜功能及音乐播放器部分功能实现。 目录 推荐排行榜优化 设置歌手、单曲跳转链接 排行榜列表渲染优化 视图修改如下: 模板修改如下: 单曲详情修改 排行榜列表 设置路由 视图处理…...
20基于MATLAB的车牌识别算法,在环境较差的情景下,夜间识别度很差的车牌号码可以精确识别出具体结果,程序已调通,可直接替换自己的数据跑。
基于MATLAB的车牌识别算法,在环境较差的情景下,夜间识别度很差的车牌号码可以精确识别出具体结果,程序已调通,可直接替换自己的数据跑。 20matlab车牌识别 (xiaohongshu.com)...
vue音频制作
Vue 音频制作指的是使用 Vue.js 框架开发音频制作相关的 Web 应用程序。Vue.js 是一种现代化的 JavaScript 框架,它可以帮助开发者更快速、更高效地构建交互式的 Web 应用程序。 音频制作在 Vue.js 中的实现可以通过使用一些开源音频库和插件来实现,如 …...
好莱坞编剧大罢工终于结束;与OpenAI创始人共进早餐;使用DALL-E 3制作绘本分享;生成式AI的基础设施架构 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🔥 好莱坞编剧大罢工终于结束:简单说就是AI妥协了 https://www.wgacontract2023.org/the-campaign/summary-of-the-2023-wga-…...
buuctf week2-web-ez_sql
闭合之后尝试判断字段数,存在WAF,使用大小写绕过(后面的sql语句也需要进行大小写绕过) ?id1 Order by 5-- 测出有5列 ?id1 Order by 6-- 查一下数据库名、版本、用户等信息 ?id1Union Select database(),version(),user(),4,…...
实验2.1.2 交换机的常用配置
项目2 交换技术的位置 活动2 交换机的常用配置 一、具体要求: (1)添加1台计算机,将标签名更改为PC1。 (2)添加1台S3700-26C-HI交换机,标签名为SWA,将交换机的名称设置为SWA。 &am…...
功率放大器应用场景分析报告
功率放大器作为一种能够将低电压信号放大到高电压水平的关键设备,在多个领域中发挥着重要作用。报告通过对实验研究、射频通信、能源与电力系统、医疗诊断与治疗以及工业自动化等领域的综合分析,下面西安安泰为大家介绍功率放大器的应用场景。 实验研究 …...
解决 Centos 安装 Python 3.10 的报错: Could not import runpy module
操作环境:CentOS 7、Gcc 4.8.5、Python 3.10.0 系统上已经有 2.x,3.6 版本的 Python 了,但是还是想装一个 3.10 的。因为刚写的脚本文件是较高版本的,在 3.6 上无法正常运行,Python 语法不是很了解,只能从…...
HTML5简介-HTML5 新增语义化标签-HTML5 新增多媒体标签
一、HTML5简介 HTML5,全称为HyperText Markup Language 5,是HTML的第五个版本,由万维网联盟(World Wide Web Consortium,W3C)和Web Hypertext Application Technology Working Group(WHATWG&am…...
pyqt---子线程进行gui操作导致界面崩溃
在 PyQt(或 Qt 通常)中,您不能直接在子线程中执行与 GUI 相关的操作。这可能会导致应用程序崩溃或不可预测的行为。所有与 GUI 相关的操作都应该在主线程中执行。 如果您需要在子线程完成某些操作后显示一个消息框,可以使用 PyQt…...
vue-cli 输出的模板 html 文件使用条件语句
背景 项目使用的是 vue-cli 脚手架,需要根据不同环境的配置,在输出的 html 模板中使用条件语句来生成不同的代码。 环境变量 在 .env.development 中,定义环境变量 VUE_APP_DISABLE_IP_ACCESStrue使用条件语句 第一种方法,使…...
HunyuanVideo-Foley保姆级教程:从零部署到音效生成的5个关键步骤
HunyuanVideo-Foley保姆级教程:从零部署到音效生成的5个关键步骤 1. 环境准备与镜像部署 1.1 硬件要求检查 在开始部署前,请确保您的设备满足以下最低配置要求: 显卡:NVIDIA RTX 4090/4090D(24GB显存)内…...
UniApp多主题开发避坑指南:为什么SCSS+Require比Vuex方案更优雅?
UniApp多主题开发实战:SCSS动态加载方案深度解析与性能优化 在移动应用开发领域,主题切换功能已成为提升用户体验的重要环节。UniApp作为跨平台开发框架,如何实现高效、灵活的主题管理一直是开发者关注的焦点。本文将深入探讨基于SCSS变量与动…...
PTA编程题‘Person抽象类’避坑指南:变量命名冲突、多态指针数组与输出格式化的那些坑
PTA编程题‘Person抽象类’避坑指南:变量命名冲突、多态指针数组与输出格式化的那些坑 在C面向对象编程的实战中,抽象类和派生类的设计看似简单,却暗藏诸多陷阱。许多初学者在完成PTA/LeetCode这类编程题时,往往因为一些看似微不足…...
ImageGlass架构深度解析:高性能Windows图像查看器的技术实现与优化策略
ImageGlass架构深度解析:高性能Windows图像查看器的技术实现与优化策略 【免费下载链接】ImageGlass 🏞 A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass ImageGlass作为一款轻量级、高性能的Win…...
Docker 容器中文字体及 matplotlib 环境应用
为了避开 Noto CJK 这种复杂的 TTC(TrueType Collection)大包带来的识别问题,最理想的选择是使用独立打包的 OTF 或 TTF 字体。 0. 环境检查 # 1. 更新源并安装 fontconfig apt-get update apt-get install -y fontconfig# 2. 现在 fc-cache 命令可用了,刷新系统字体 fc-…...
大模型应用指南:小白程序员必收藏,轻松入门AI前沿技术!
2025年大模型技术已在IT、金融、制造等领域广泛应用,从智能客服到数据分析,助力企业转型。沙丘智库《大模型应用跟踪月报》收录504个案例,揭示行业分布、应用场景及发展趋势。大模型不仅是技术突破,更是时代标志,小白程…...
2026年鱼生专用花生油:哪些品牌值得选?
大家好,今天咱们聊聊一个很有趣的话题——鱼生专用花生油。说到鱼生,大家可能会想到广东、广西地区的美食,尤其是那一道道色香味俱全的鱼生,简直让人垂涎欲滴。但是,鱼生的美味离不开优质的食用油,尤其是花…...
3步打造开源工具效率引擎:QtScrcpy自定义配置全指南
3步打造开源工具效率引擎:QtScrcpy自定义配置全指南 【免费下载链接】QtScrcpy Android实时投屏软件,此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限 项目地址: https://gitcode.com/barry-ran/QtScrcpy …...
ROS Noetic下大陆ARS408雷达点云数据解析:从CAN原始帧到RVIZ可视化,一个脚本全搞定
ROS Noetic下大陆ARS408雷达点云数据全链路解析与自动化实践 毫米波雷达在自动驾驶、机器人导航等领域扮演着关键角色。大陆ARS408作为一款高性价比的毫米波雷达,其点云数据的获取与可视化是许多开发者需要掌握的核心技能。本文将带您从底层CAN总线通信开始…...
Qwen3-TTS-VoiceDesign实战案例:用‘撒娇稚嫩萝莉声’描述生成高拟真TTS音频
Qwen3-TTS-VoiceDesign实战案例:用‘撒娇稚嫩萝莉声’描述生成高拟真TTS音频 1. 项目概述与核心价值 Qwen3-TTS-VoiceDesign是一个让人惊艳的语音合成模型,它最大的特点就是能用简单的文字描述,生成你想要的任何声音风格。想象一下…...
