当前位置: 首页 > news >正文

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并发服务器的实现流程&#xff1a;一、自定义信号处理函数&#xff08;sig_func函数&#xff09;&#xff1a; void sig_func(int signum){wait(NULL);}wait函数: #include <sys/types.h>#include <sys/wait.h>pid_t wait(int *wstatus);/*功能&#…...

VSCode 快速移动光标至行尾

最近在用vscode进行C编程&#xff0c;经常需要把光标跳到行尾去添加符号。 手动到行尾太麻烦了。 一种快捷方式是&#xff1a;用键盘上的“END”快捷键。 但是用这个键也不是很方便&#xff0c;因为“end”键离主键盘区太远。 另一种便捷的方式是&#xff1a;给vscode设置自定义…...

ACP.复盘方法

复盘要怎么做的有水准&#xff0c;让领导满意&#xff0c;方式方法很重要。今天给你们安利5种复盘方法&#xff0c;保准你省事&#xff0c;领导还满意。 一、KPT复盘法 7月份年中一直在做和复盘相关的事&#xff0c;像公司的OKR复盘、年中战略规划&#xff0c;不过日常很多生…...

Springboot 订餐管理系统idea开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 订餐管理系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有 完整的源代码和数据库&…...

判断当前Activity是否有DialogFragment显示

DialogFragment一种情况是在当前Activity上启动&#xff0c;一种情况是在Fragment上启动&#xff0c;判断当前fragmentManager上是否有&#xff0c;以及遍历判断子fragment上是否有&#xff0c;即可确定是否有DialogFragment展示。 使用方式&#xff1a; // 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”目录下&#xff0c;如下图所示&#xff1a; 在 Sobel 算子算法函数中&#xff0c;如果设置 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 新特性解读:体验与协作全面提升

作者&#xff1a;徽泠(苏墨馨) 为了庆祝 Grafana 的 10 年里程碑&#xff0c;Grafana Labs 推出了 Grafana 10&#xff0c;这个具有纪念意义的版本强调增强用户体验&#xff0c;使各种开发人员更容易使用。Grafana v10.0.x 为开发者与企业展示卓越的新功能、可视化与协作能力&…...

Django实现音乐网站 ⒆

使用Python Django框架做一个音乐网站&#xff0c; 本篇主要为排行榜功能及音乐播放器部分功能实现。 目录 推荐排行榜优化 设置歌手、单曲跳转链接 排行榜列表渲染优化 视图修改如下&#xff1a; 模板修改如下&#xff1a; 单曲详情修改 排行榜列表 设置路由 视图处理…...

20基于MATLAB的车牌识别算法,在环境较差的情景下,夜间识别度很差的车牌号码可以精确识别出具体结果,程序已调通,可直接替换自己的数据跑。

基于MATLAB的车牌识别算法&#xff0c;在环境较差的情景下&#xff0c;夜间识别度很差的车牌号码可以精确识别出具体结果&#xff0c;程序已调通&#xff0c;可直接替换自己的数据跑。 20matlab车牌识别 (xiaohongshu.com)...

vue音频制作

Vue 音频制作指的是使用 Vue.js 框架开发音频制作相关的 Web 应用程序。Vue.js 是一种现代化的 JavaScript 框架&#xff0c;它可以帮助开发者更快速、更高效地构建交互式的 Web 应用程序。 音频制作在 Vue.js 中的实现可以通过使用一些开源音频库和插件来实现&#xff0c;如 …...

好莱坞编剧大罢工终于结束;与OpenAI创始人共进早餐;使用DALL-E 3制作绘本分享;生成式AI的基础设施架构 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f525; 好莱坞编剧大罢工终于结束&#xff1a;简单说就是AI妥协了 https://www.wgacontract2023.org/the-campaign/summary-of-the-2023-wga-…...

buuctf week2-web-ez_sql

闭合之后尝试判断字段数&#xff0c;存在WAF&#xff0c;使用大小写绕过&#xff08;后面的sql语句也需要进行大小写绕过&#xff09; ?id1 Order by 5-- 测出有5列 ?id1 Order by 6-- 查一下数据库名、版本、用户等信息 ?id1Union Select database(),version(),user(),4,…...

实验2.1.2 交换机的常用配置

项目2 交换技术的位置 活动2 交换机的常用配置 一、具体要求&#xff1a; &#xff08;1&#xff09;添加1台计算机&#xff0c;将标签名更改为PC1。 &#xff08;2&#xff09;添加1台S3700-26C-HI交换机&#xff0c;标签名为SWA&#xff0c;将交换机的名称设置为SWA。 &am…...

功率放大器应用场景分析报告

功率放大器作为一种能够将低电压信号放大到高电压水平的关键设备&#xff0c;在多个领域中发挥着重要作用。报告通过对实验研究、射频通信、能源与电力系统、医疗诊断与治疗以及工业自动化等领域的综合分析&#xff0c;下面西安安泰为大家介绍功率放大器的应用场景。 实验研究 …...

解决 Centos 安装 Python 3.10 的报错: Could not import runpy module

操作环境&#xff1a;CentOS 7、Gcc 4.8.5、Python 3.10.0 系统上已经有 2.x&#xff0c;3.6 版本的 Python 了&#xff0c;但是还是想装一个 3.10 的。因为刚写的脚本文件是较高版本的&#xff0c;在 3.6 上无法正常运行&#xff0c;Python 语法不是很了解&#xff0c;只能从…...

HTML5简介-HTML5 新增语义化标签-HTML5 新增多媒体标签

一、HTML5简介 HTML5&#xff0c;全称为HyperText Markup Language 5&#xff0c;是HTML的第五个版本&#xff0c;由万维网联盟&#xff08;World Wide Web Consortium&#xff0c;W3C&#xff09;和Web Hypertext Application Technology Working Group&#xff08;WHATWG&am…...

pyqt---子线程进行gui操作导致界面崩溃

在 PyQt&#xff08;或 Qt 通常&#xff09;中&#xff0c;您不能直接在子线程中执行与 GUI 相关的操作。这可能会导致应用程序崩溃或不可预测的行为。所有与 GUI 相关的操作都应该在主线程中执行。 如果您需要在子线程完成某些操作后显示一个消息框&#xff0c;可以使用 PyQt…...

vue-cli 输出的模板 html 文件使用条件语句

背景 项目使用的是 vue-cli 脚手架&#xff0c;需要根据不同环境的配置&#xff0c;在输出的 html 模板中使用条件语句来生成不同的代码。 环境变量 在 .env.development 中&#xff0c;定义环境变量 VUE_APP_DISABLE_IP_ACCESStrue使用条件语句 第一种方法&#xff0c;使…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...