[Linux网络编程]04-多进程/多线程并发服务器思路分析及实现(进程,信号,socket,线程...)
一.思路
实现一个服务器可以连接多个客户端,每当accept函数等待到客户端进行连接时 就创建一个子进程;
核心思路:让accept循环阻塞等待客户端,每当有客户端连接时就fork子进程,让子进程去和客户端进行通信,父进程用于监听并使用信号捕捉回收子进程;(子进程关闭用于监听的套接字lfd,父进程关闭用于通信的cfd)
二.多进程并发服务器代码实现:
1.利用while 和 accept 阻塞等待客户端连接,一旦有一个客户端连接上,就创建一个新的子进程执行服务逻辑。
2.子进程结束时,利用信号捕捉函数sigaction回收子进程
3.注意,当主进程阻塞在accept时,若子进程发出信号,accept会被打断(一系列慢速系统调用的特点)从而直接执行接下来的fork函数,这就会导致一个子进程刚好被回收后,又会产生一个新的子进程,为了防止这种情况,使用again和goto维护accept,防止被信号打断后产生错误。
1 #include<iostream> 2 #include<unistd.h>3 #include<sys/socket.h>4 #include<arpa/inet.h>5 #include<signal.h>6 #include<sys/wait.h>7 using namespace std;8 9 void huidiao(int signo)10 {11 pid_t pid;12 while((pid = waitpid(-1,NULL,WNOHANG))>0)13 {14 cout<<pid<<endl;15 }16 return ;17 }18 19 int main()20 { 21 struct sigaction act;22 act.sa_handler = huidiao; sigemptyset(&act.sa_mask);24 act.sa_flags = 0;25 sigaction(SIGCHLD,&act,NULL);26 //socket bind listen accept27 int fd = socket(AF_INET,SOCK_STREAM,0);28 struct sockaddr_in serveraddr,clientaddr;29 serveraddr.sin_family = AF_INET;30 serveraddr.sin_port = htons(9876);31 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);32 bind(fd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));33 34 listen(fd,128);35 36 socklen_t clientaddr_len = sizeof(clientaddr);37 int sfd,flag;38 while(true)39 {40 sfd = accept(fd,(struct sockaddr*)&clientaddr,&clientaddr_len);41 flag = fork();42 43 if(flag == 0)44 { close(fd);46 break;47 }48 else if(flag <0)49 {50 exit(1);51 }52 else if(flag>0) 53 {54 close(sfd);55 continue;56 }57 } 58 59 if(flag == 0)60 { 61 for(;;)62 {63 char buf[1024];64 int n = read(sfd,buf,sizeof(buf));65 if(n==0)66 { close(sfd);68 cout<<"jieshu"<<endl;69 exit(0);70 }71 for(int i = 0;i<n;i++)72 {73 buf[i] = toupper(buf[i]);74 }75 write(STDOUT_FILENO,buf,n);76 write(sfd,buf,n);77 }78 }79 return 0;80 }
三. 多线程并发服务器代码实现:
1.#include <stdio.h>
2.#include <string.h>
3.#include <arpa/inet.h>
4.#include <pthread.h>
5.#include <ctype.h>
6.#include <unistd.h>
7.#include <fcntl.h>
8.
9.#include "wrap.h"
10.
11.#define MAXLINE 8192
12.#define SERV_PORT 8000
13.
14.struct s_info { //定义一个结构体, 将地址结构跟cfd捆绑
15. struct sockaddr_in cliaddr;
16. int connfd;
17.};
18.
19.void *do_work(void *arg)
20.{
21. int n,i;
22. struct s_info *ts = (struct s_info*)arg;
23. char buf[MAXLINE];
24. char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16 可用"[+d"查看
25.
26. while (1) {
27. n = Read(ts->connfd, buf, MAXLINE); //读客户端
28. if (n == 0) {
29. printf("the client %d closed...\n", ts->connfd);
30. break; //跳出循环,关闭cfd
31. }
32. printf("received from %s at PORT %d\n",
33. inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),
34. ntohs((*ts).cliaddr.sin_port)); //打印客户端信息(IP/PORT)
35.
36. for (i = 0; i < n; i++)
37. buf[i] = toupper(buf[i]); //小写-->大写
38.
39. Write(STDOUT_FILENO, buf, n); //写出至屏幕
40. Write(ts->connfd, buf, n); //回写给客户端
41. }
42. Close(ts->connfd);
43.
44. return (void *)0;
45.}
46.
47.int main(void)
48.{
49. struct sockaddr_in servaddr, cliaddr;
50. socklen_t cliaddr_len;
51. int listenfd, connfd;
52. pthread_t tid;
53.
54. struct s_info ts[256]; //创建结构体数组.
55. int i = 0;
56.
57. listenfd = Socket(AF_INET, SOCK_STREAM, 0); //创建一个socket, 得到lfd
58.
59. bzero(&servaddr, sizeof(servaddr)); //地址结构清零
60. servaddr.sin_family = AF_INET;
61. servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定本地任意IP
62. servaddr.sin_port = htons(SERV_PORT); //指定端口号
63.
64. Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定
65.
66. Listen(listenfd, 128); //设置同一时刻链接服务器上限数
67.
68. printf("Accepting client connect ...\n");
69.
70. while (1) {
71. cliaddr_len = sizeof(cliaddr);
72. connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //阻塞监听客户端链接请求
73. ts[i].cliaddr = cliaddr;
74. ts[i].connfd = connfd;
75.
76. pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
77. pthread_detach(tid); //子线程分离,防止僵线程产生.
78. i++;
79. }
80.
81. return 0;
82.}
相关文章:
[Linux网络编程]04-多进程/多线程并发服务器思路分析及实现(进程,信号,socket,线程...)
一.思路 实现一个服务器可以连接多个客户端,每当accept函数等待到客户端进行连接时 就创建一个子进程; 核心思路:让accept循环阻塞等待客户端,每当有客户端连接时就fork子进程,让子进程去和客户端进行通信,父进程用于…...
《OpenCV计算机视觉》—— 年龄与性别预测
结合以下链接中的文章有助于理解此篇案例: OpenCV中的 cnn 模块 https://blog.csdn.net/weixin_73504499/article/details/142965441?spm1001.2014.3001.5501 此案例是通过使用OpenCV中的cnn模块来调用别人已经训练好的深度学习模型,此篇案例中用到了…...
详解23种设计模式——第一部分:概述+创建型模式
目录 1. 概述 2. 创建型模式 2.1 简单(静态)工厂模式 2.1.1 介绍 2.1.2 实现 2.2 工厂模式 2.3 抽象工厂模式 2.4 单例模式 2.4.1 饿汉模式 2.4.2 懒汉模式 2.4.3 线程安全的懒汉式 2.4.4 DCL单例 - 高性能的懒汉式 2.5 建造者模式 2.6 原…...
semi-Naive Bayesian(半朴素贝叶斯)
semi-Naive Bayesian(半朴素贝叶斯) 引言 朴素贝叶斯算法是基于特征是相互独立这个假设开展的(为了降低贝叶斯公式: P ( c ∣ x ) P ( c ) P ( x ∣ c ) P ( x ) P(c|x) \frac {P(c)P(x|c)}{P(x)} P(c∣x)P(x)P(c)P(x∣c)中后验概率 P …...
大语言模型(LLM)入门级选手初学教程
链接:https://llmbook-zh.github.io/ 前言: GPT发展:GPT-1 2018 -->GPT-2&GPT-3(扩大预训练数据和模型参数规模)–> GPT-3.5(代码训练、人类对齐、工具使用等)–> 2022.11 ChatG…...
HTML 实例/测验之HTML 基础一口气讲完!(o-ωq)).oO 困
HTML 基础 非常简单的HTML文档 <!DOCTYPE html> <html><head><title>页面标题(w3cschool.cn)</title></head><body><h1>我的第一个标题</h1><p>我的第一个段落。</p></body> </html> 输出&a…...
c语言基础程序——经典100道实例。
c语言基础程序——经典100道实例 001, 组无重复数字的数002,企业发放的奖金根据利润提成003,完全平方数004,判断当天是这一年的第几天005,三个数由小到大输出006,输出字母C图案007,特殊图案008&…...
火星求生CE修改金钱,无限资金
由于火星求生前期没有资金非常难玩,想通过修改资金渡过前期,网上找了一圈修改器,只有修改无限声望和无限科研,就是没有无限资金,于是自己用CE修改 教程 首先查看自己资金是多少M,如下图我是22430M资金&…...
linux 内存管理-slab分配器
伙伴系统用于分配以page为单位的内存,在实际中很多内存需求是以Byte为单位的,如果需要分配以Byte为单位的小内存块时,该如何分配呢? slab分配器就是用来解决小内存块分配问题,也是内存分配中非常重要的角色之一。 slab分配器最终还是由伙伴系统分配出实际的物理内存,只不过s…...
docker-compose部署gitlab(亲测有效)
一.通过DockerHub拉取Gitlab镜像 docker pull gitlab/gitlab-ce:latest 二.创建目录 mkdir -p /root/tool/gitlab/{data,logs,config} && cd /root/tool/gitlab/ 三.编辑DockerCompose.yaml文件 vim /root/tool/gitlab/docker-compose.yml version: "3&quo…...
Leetcode 赎金信
利用hash map做 java solution class Solution {public boolean canConstruct(String ransomNote, String magazine) {//首先利用HashMap统计magazine中字符频率HashMap<Character, Integer> magazinefreq new HashMap<>();for(char c : magazine.toCharArray())…...
S7--环境搭建基本操作
1.修改蓝牙名称和地址 工程路径:$ADK_ROOT\adk\src\filesystems\CDA2\factory_default_config\ 在subsys7_config5.htf中 DeviceName = "DEVICE_NAME“ # replace with your device name BD_ADDRESS=[00 FF 00 5B 02 00] # replace with your BD address 2.earbud工程修改…...
webAPI中的排他思想、自定义属性操作、节点操作(配大量案例练习)
一、排他操作 1.排他思想 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法: 1.所有的元素全部清除样式 2.给当前的元素设置样式 注意顺序能不能颠倒,首先清除全部样式,再设置自己当前的…...
101、QT摄像头录制视频问题
视频和音频录制类QMediaRecorder QMediaRecorder 通过摄像头和音频输入设备进行录像。 注意: 使用Qt多媒体模块的摄像头相关类无法在Windows平台上进行视频录制,只能进行静态图片抓取但是在Linux平台上可以实现静态图片抓取和视频录制。 Qt多媒体模块的功能实现是依…...
FairGuard游戏加固全面适配纯血鸿蒙NEXT
2024年10月8日,华为正式宣布其原生鸿蒙操作系统 HarmonyOS NEXT 进入公测阶段,标志着其自有生态构建的重要里程碑。 作为游戏安全领域领先的第三方服务商,FairGuard游戏加固在早期就加入了鸿蒙生态的开发,基于多项独家技术与十余年…...
鲸信私有化即时通信如何平衡安全性与易用性之间的关系?
即时通信已经成为我们生活中不可或缺的一部分。从日常沟通到工作协作,每一个信息的传递都承载着信任与效率。然而,随着网络安全威胁日益严峻,如何在享受即时通信便捷的同时,确保信息的私密性与安全性,成为了摆在我们面…...
vivado 接口带宽验证
存储器接口 使用赛灵思存储器 IP 时需要更多的 I/O 管脚分配步骤。自定义 IP 之后,您可采用 Vivado IDE 中的细化 (elaborated) 或综 合 (synthesized) 设计分配顶层 IP 端口到物理封装引脚。同每一个存储器 IP 关联的所有端口都被纳入一个 I/O 端口接口…...
Qt中使用线程之QThread
使用Qt中自带的线程类QThread时 1、需要定义一个子类继承自QThread 2、重写run()方法,在run方法中编写业务逻辑 3、子类支持信号槽 4、子类的构造函数的执行是在主线程进行的,而run方法的执行是在子线程中进行的 常用方法 静态方法 获取线程id 可…...
多IP连接
一.关闭防火墙 systemctl stop firewalld setenforce 0 二.挂在mnt mount /dev/sr0 /mnt 三.下载nginx dnf install nginx -y 四.启动nginx协议 systemctl start nginx 五.修改协议 vim /etc/nginx/nginx.conf 在root前加#并且下一行添加 root /www:(浏…...
Linux重点yum源配置
1.配置在线源 2.配置本地源 3.安装软件包 4.测试yum源配置 5.卸载软件包...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
