[C语言]带连接数统计功能的多进程TCP服务器

编程思想:

so,我们一分钱没花改造了一个简易TCP服务器,具体的:

1 当accept正常返回后,创建一个子进程用于处理数据

2 在子进程中 关闭socket返回的fd,在父进程中关闭accept返回的fd,防止资源泄露及不可预知的风险

3 父进程中忽略子进程结束信号,等于自动回收,防止变僵尸

当有了一个主体结构可以运行,如何观察这种并发的效果???

每连接一个客户端,计数器加1 ,处理完成计数器减1,但使用什么可以完成这种效果?

全局变量?每个进程都有自己的全局变量 修改自己的别人看不见

信号量隆重登场! posix风格的信号量不同于system V,开局直接设0,还可以进程间共享,每当一个连接加入就加1,每当一个连接处理完进程退出就减1,用完就关上,重开代码先unlink

注意事项:

1 使用if判断函数的返回值

2 子进程结束 必须使用exit函数,否则可以观察到不符合逻辑的超自然现象

3 赠送手动运行客户端 可以编译后在多个终端运行,也可在IDE中运行多次观察效果

服务端:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>#define SERVER_IP "192.168.142.132"
#define SERVER_PORT 50007int main()
{int server_sockfd, client_sockfd;struct sockaddr_in server_sockaddr, client_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));memset(&client_sockaddr, 0, sizeof(client_sockaddr));socklen_t client_sockaddr_len = sizeof(client_sockaddr);socklen_t server_sockaddr_len = sizeof(server_sockaddr);ssize_t send_bytes, recv_bytes;char send_buf[1024] = "How can I help you today ?";char recv_buf[1024] = {0};sem_unlink("/sem1");server_sockfd = socket(AF_INET, SOCK_STREAM, 0);if (server_sockfd == -1){perror("socket");}int optval = 1;if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1){perror("setsockopt");}server_sockaddr.sin_port = htons(SERVER_PORT);inet_pton(AF_INET, SERVER_IP, &server_sockaddr.sin_addr.s_addr);server_sockaddr.sin_family = AF_INET;if ((bind(server_sockfd, (struct sockaddr *)&server_sockaddr, server_sockaddr_len)) == -1){perror("bind");}if ((listen(server_sockfd, 16)) == -1){perror("listen");}sem_t *sem = sem_open("/sem1", O_CREAT, 0777, 0);if (sem == SEM_FAILED){perror("sem_open");}printf("listening on : %d\n", SERVER_PORT);while (1){client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_sockaddr, &client_sockaddr_len);if (client_sockfd == -1){perror("accept");}pid_t pid = fork();if (pid == 0){sem_post(sem);int sval;sem_getvalue(sem, &sval);printf("V [+] connected : %d\n", sval);if (close(server_sockfd) == -1){perror("close");}recv_bytes = recv(client_sockfd, recv_buf, sizeof(recv_buf), 0);if (recv_bytes == -1){perror("recv");}if (recv_bytes == 0){printf("close by peer\n");}if (recv_bytes > 0){printf("Message : %s\n", recv_buf);}sleep(9);send_bytes = send(client_sockfd, send_buf, strlen(send_buf), 0);if (send_bytes == -1){perror("send");}if (close(client_sockfd) == -1){perror("close");}sem_wait(sem);printf("P [-] job done \n");sem_close(sem);exit(EXIT_SUCCESS);}else if (pid > 0){if (signal(SIGCHLD, SIG_IGN) == SIG_ERR){perror("signal");}if (close(client_sockfd) == -1){perror("close");}}else{perror("fork");}}return 0;
}

客户端:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>#define SERVER_IP "192.168.142.132"
#define SERVER_PORT 50007int main()
{int client_sockfd;struct sockaddr_in server_sockaddr, client_sockaddr;memset(&server_sockaddr, 0, sizeof(server_sockaddr));memset(&client_sockaddr, 0, sizeof(client_sockaddr));socklen_t client_sockaddr_len = sizeof(client_sockaddr);ssize_t send_bytes, recv_bytes;char send_buf[1024] = {"hello server !!!"};char recv_buf[1024] = {0};client_sockfd = socket(AF_INET, SOCK_STREAM, 0);inet_pton(AF_INET, SERVER_IP, &server_sockaddr.sin_addr.s_addr);server_sockaddr.sin_port = htons(SERVER_PORT);server_sockaddr.sin_family = AF_INET;connect(client_sockfd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr));send_bytes = send(client_sockfd, send_buf, strlen(send_buf), 0);recv_bytes = recv(client_sockfd, recv_buf, sizeof(recv_buf), 0);printf("%s\n", recv_buf);close(client_sockfd);return 0;
}

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

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

相关文章

hdlbits系列verilog解答(Hadd)-65

文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 本节我们创建一个半加法器。半加法器将两个位相加(无进位)并产生求和和进出。 模块声明 module top_module( input a, b, output cout, sum ); 思路: 可用真值表写出逻辑表达式,或者直接用数据流方式。 二…

Qt 压缩/解压文件

前面讲了很多Qt的文件操作&#xff0c;文件操作自然就包括压缩与解压缩文件了&#xff0c;正好最近项目里要用到压缩以及解压缩文件&#xff0c;所以就研究了一下Qt如何压缩与解压缩文件。 QZipReader/QZipWriter QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文…

linux 多个文件(csv)合并成一个文件(csv)

文章目录 前言实例:实战:另外&#xff0c;补充一个相关知识 总结 前言 Linux之cat合并多个文件 实例: # 将当前目录下所有csv结尾的文件合并到merge.csv cat *.csv > merge.csv # 当然也可以指定合并哪几个文件 cat db1.sql db2.sql db3.sql > db_all.sql 实战: 将每个…

好物视频素材哪里找?推荐以下几个自用很好的视频素材库

好物视频素材哪里找&#xff1f;这可是个让很多创作者头疼的问题。想制作一个吸引人的视频&#xff0c;好的素材可是关键。下面就给大家介绍几个热门的视频素材网站&#xff0c;希望能帮到你&#xff01; 蛙学网&#xff08;https://www.waxuewang.com/&#xff09;&#xff1…

国产数据库序列机制

数据库 达梦 序列&#xff1a;支持 主键自增&#xff1a;支持 使用序列 //1.创建序列 create sequence <序列名> increment by 10...; //2.使用序列&#xff0c;插入时指定&#xff0c;或者设计表字段默认值为seq1.nextval insert into <表名>(id,...) values…

netty构建udp服务器以及发送报文到客户端客户端详细案例

目录 一、基于netty创建udp服务端以及对应通道设置关键 二、发送数据 三、netty中的ChannelOption常用参数说明 1、ChannelOption.SO_BACKLOG 2、ChannelOption.SO_REUSEADDR 3、ChannelOption.SO_KEEPALIVE 4、ChannelOption.SO_SNDBUF和ChannelOption.SO_RCVBUF 5、Ch…

vs code

vs code 下载安装 https://code.visualstudio.com/https://code.visualstudio.com/ 下载完后&#xff0c;下一步下一步就安装完了&#xff0c;安装好后可以下载各种好用的插件

无需 VPN 即可急速下载 huggingface 上的 LLM 模型

无需 VPN 即可急速下载 huggingface 上的 LLM 模型 无需 VPN 即可急速下载 huggingface 上的 llm 模型安装依赖配置下载命令 无需 VPN 即可急速下载 huggingface 上的 llm 模型 快速下载huggingface模型&#xff1a; 安装依赖 pip install -U huggingface_hub hf_transfer …

已注册的商标别忘了续展,新注可能难下证!

近期普推知产老杨遇到好几个网友和看过多个案例&#xff0c;以前商标名称可以申请注册下来&#xff0c;但是换字体注册不下来了&#xff0c;有的是不想续展想直接换字体申请注册&#xff0c;但是也没有下来。 这些商标名称主要是存在禁止注册或缺显&#xff0c;比如“柳林”以前…

蓝桥杯每日一题:修建灌木

题目来源: 第十三届蓝桥杯大赛软件赛省赛B组 爱丽丝要完成修建灌木的工作 有 N N N 棵灌木整齐的从左向右排成一排, 爱丽丝在每天傍晚会修建一棵灌木, 让灌木的高度变为 0 厘米. 修建灌木的顺序是从最左侧的灌木开始, 每天向右修建一棵灌木. 当修建了最右侧的灌木之后, 她会调…

ensp静态路由综合实验(一)

实验拓扑&#xff1a; 实验目的&#xff1a; 1、R6为ISP&#xff0c;接口IP地址均为公有地址&#xff0c;该设备只能配置IP地址&#xff0c;之后不能再对其进行任何配置&#xff1b; 2、R1-R5为局域网&#xff0c;私有IP地址192.168.1.0/24&#xff0c;请合理分配&#xff1b;…

Web API —— BOM 学习(完结)

目录 一、BOM 介绍 二、Window 对象 &#xff08;一&#xff09;基本介绍 &#xff08;二&#xff09;定时器 —— 延时函数 1.语法 2.清除时间函数 3.和 interval 间歇函数的区别 &#xff08;三&#xff09;JS 执行机制 1.介绍 2.同步任务 3.异步任务 4.执行过程…

Go与Java深度对比:从语言特性到应用场景的全面分析

Go&#xff08;Golang&#xff09;和Java是两种流行的编程语言&#xff0c;它们在设计哲学、应用领域和生态系统方面有着独特的特点。以下是对这两种语言的全方位对比&#xff1a; 语言历史与发展 Go&#xff1a; Go语言由Robert Griesemer、Rob Pike和Ken Thompson在2007年…

编程出现bug?怎么用Python打印异常

在 Python 编程中&#xff0c;异常是指程序执行过程中出现的错误或异常情况。当程序遇到异常时&#xff0c;为了更好地调试和定位问题&#xff0c;我们需要打印异常信息。本文将详细介绍如何在 Python 中打印异常&#xff0c;并提供一些示例和注意事项。 一、try-except 语句捕…

一、CentOS基础命令(2.系统与用户操作)

文章目录 2、用户管理&#xff08;1.&#xff09;useradd - 创建新用户&#xff08;2.&#xff09;userdel - 删除用户&#xff08;3.&#xff09;usermod - 修改用户属性&#xff08;4.&#xff09;passwd - 管理用户密码&#xff08;5.&#xff09;groupadd - 创建用户组&…

C语言程序编译和链接的

目录 引言 编译与链接概览 编译过程详解 链接过程解读 结论 引言 在编程实践中&#xff0c;《程序员的自我修养》一书为我们揭示了构建高质量软件背后的重要环节——编译与链接。这两个过程对于C语言程序从源代码到可执行文件的蜕变至关重要&#xff0c;它们是每一个开发…

python ACM格式 || stdin和input的区别 || acm中常用的函数

疑问 在acm格式里有两种方法读取用户输入&#xff1a; import sys 然后使用 sys.stdininput() 但隐隐约约感觉这两个方法读到的数据在最后一行有些问题 导致我在使用stdin时候&#xff0c;需要使用正则表达式&#xff1a;re.split(‘[,\n]’,textline)来把一个以逗号分割的字…

C++资产设备管理系统

一、引言 1.1 项目设计背景及意义 1.1.1理论研究基础 &#xff08;1&#xff09;C在C的基础上增加了面向对象的机制。 &#xff08;2&#xff09;充分利用面向对象机制中的多态性实现函数的设计。 1.1.2 技术层面的支持 运用系统为C面向对象程序设计提供的各种设计方法和V…

24.park和unpark方法

1.park方法可以暂停线程&#xff0c;线程状态为wait。 2.unpark方法可以恢复线程&#xff0c;线程状态为runnable。 3.LockSupport的静态方法。 4.park和unpark方法调用不分先后&#xff0c;unpark先调用&#xff0c;park后执行也可以恢复线程。 public class ParkDemo {pu…

冗余双写方案下数据一致性问题解决及延申问题处理方案

主要整理了采用冗余双写方案后的问题解决方案。 1、问题&#xff1a;冗余双写场景下&#xff0c;如何解决数据一致性问题&#xff1f; 方案一&#xff1a; 直接RPC调用Seata分布式事务框架&#xff0c;采用该方式实现了事务的强一致性&#xff0c;代码逻辑简单的同时业务侵入…