[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.}  

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

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

相关文章

软考(中级-软件设计师)算法分析篇(1024)

三、算法设计与分析 #1024程序员节|正文# 一、分治法 1.1 分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易的解决&#xff08;比如说规模较小&#xff0c;则直接解决&#xff0c;否则将其分解为k个规模较小的问题&#xff0c;这些子问题相互独立且与原问题形…

数组类型应用举例

在main.cpp里输入程序如下&#xff1a; #include "stdio.h" //使能printf()函数 #include <stdlib.h> //使能exit(); #define My_array_Size 10 //定义用My_array_Size代替 unsigned char My_array[My_array_Size]; //声明数组My_arra…

集群分发脚本

我的后端学习大纲 我的Linux环境搭建学习大纲 8.2.scp安全拷贝: 1.命令格式&#xff1a;scp -r $pdir/$fname $user$host:$pdir/$fname2.具体命令&#xff1a; scp -r jdk1.8.0_321/ rootHadoop104:/opt/module 3.实际操作&#xff1a; 3.1.在hadoop2和hadoop3&#xff0c;had…

Verilog 0x01 基础

硬件描述语言 0x00 数电逻辑符号 与 & 或 | 异或 ^ 同或 ~^0x01 基本结构 1.1 线网&#xff08;wire&#xff09; wire 类型表示硬件单元之间的物理连线&#xff0c;由其连接的器件输出端连续驱动 如果没有驱动元件连接到 wire 型变量&#xff0c;缺省值一般为 “Z” …

h5页面与小程序页面互相跳转

小程序跳转h5页面 一个home页 /pages/home/home 一个含有点击事件的元素&#xff1a;<button type"primary" bind:tap"toWebView">点击跳转h5页面</button>toWebView(){ wx.navigateTo({ url: /pages/webview/webview }) } 一个webView页 /pa…

数据结构——队列和栈

目录 一、栈 1、概念与结构 2、栈的结构与初始化 3、入栈 4、出栈 5、取栈顶元素 6、取栈中有效元素个数 7、栈是否为空 二、队列 1、概念与结构 2、队列的结构与初始化 3、入队列 4、出队列 5、取队头数据 6、取队尾数据 7、队列判空 8、队列中有效元素个数 练习题目链 一…

(一)Mysql篇---Mysql整体架构

MySql框架浅析 首先&#xff0c;上一张图先让各位看看大致结构&#xff1a; 从上到下&#xff0c;依次说一下结构&#xff1a; 连接层&#xff1a;这里主要是处理客户端和数据库连接的&#xff0c;直接使用的Tomcat的连接池&#xff0c;可以调整最大连接数&#xff1b; 服务…

精益思维在新能源汽车研发中的应用体现

近年来&#xff0c;新能源汽车作为绿色出行的重要载体&#xff0c;其研发与生产模式正经历着深刻的变革。精益思维&#xff0c;这一源自制造业的管理理念&#xff0c;正逐步渗透并深刻影响着新能源汽车的研发过程&#xff0c;不仅提升了产品质量与生产效率&#xff0c;还促进了…

汽车级DC-DC转换器英飞凌TLF35584

上汽荣威都在用的汽车级DC-DC转换器英飞凌TLF35584 今天平台君从IPBrain数据库中给大家带来的一款由Infineon(英飞凌)推出的一款多路输出安全电源芯片,具备高可靠性和安全性。适用于汽车电子系统中的多种应用场景,如车身控制、安全气囊、防抱死制动系统,电子稳定控制系统等。…

数据结构:堆的应用

堆排序 假定有一组数据极多的数&#xff0c;让我们进行排序&#xff0c;那我们很容易想到一种经典的排序方法&#xff0c;冒泡排序&#xff0c;我们对冒泡排序的时间复杂度进行分析&#xff1a; 显然&#xff0c;冒泡排序的时间复杂度是O&#xff08;n^2&#xff09;,当数据量…

软考(中级-软件设计师)计算机系统篇(1024)

#1024程序员节|正文# 六、树和二叉树 6.1 树的基本概念 描述结果结点的度子结点的个数树的度最大结点的度叶子结点没有子结点的结点内部结点除根结点和叶子结点外的结点父节点有子结点的结点子节点有父结点的结点兄弟节点有同一个父结点的结点层次4层 6.2 二叉树的基本概念…

【Javaee】网络原理—TCP协议的核心机制

前言 TCP/IP五层协议是互联网中的主流模型&#xff0c;为网络通信提供了一个稳固的框架。 主要包含了应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;物理层。 本篇主要介绍传输层的TCP协议的核心机制 一. 确认应答&#xff08;ack&#xf…

线程本地变量-ThreadLocal

一、ThreadLocal简介 ThreadLocal叫做线程变量&#xff0c;意思是ThreadLocal中填充的变量属于当前线程&#xff0c;该变量对其他线程而言是隔离的&#xff0c;也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本&#xff0c;那么每个线程可…

量子纠错--shor‘s 码

定理1 (量子纠错的条件) C是一组量子编码&#xff0c;P是映射到C上的投影算子。假设是一个算子元素描述的量子操作&#xff0c;那么基于量子编码C&#xff0c;存在一个能对抗描述的噪声的纠错操作R的充要条件是 对某个复元素厄米矩阵成立。 将算子元素称为导致的错误。如果这样…

[C++进阶数据结构]红黑树(半成品)

我们讲完了AVL树,它追求绝对平衡&#xff0c;从而导致插入和删除性能较差。今天我们来讲讲&#xff0c;红黑树&#xff0c;它是另一种平衡二叉搜索树&#xff0c;它追求相对平衡&#xff0c;使得增删查改的性能都极佳&#xff0c;时间复杂度皆为O(log2N)。 一、红黑树的概念 …

CSS3 动画相关属性实例大全(三)(columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性)

CSS3 动画相关属性实例大全&#xff08;三) &#xff08;columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性&#xff09; 本文目录&#xff1a; 一、columns属性&#xff08;设置元素的列宽和列数&#xff09; 二、filter属性&#xff08;调整图像、背景和边…

Ribbon客户端负载均衡策略测试及其改进

文章目录 一、目的概述二、验证步骤1、源码下载2、导入IDE3、运行前修改配置4、策略说明5、修改策略 三、最终结论四、改进措施1. 思路分析2. 核心代码3. 测试页面 一、目的概述 为了验证Ribbon客户端负载均衡策略在负载节点失效的情况下&#xff0c;是否具有故障转移的功能&a…

【逆向基础】十七、PE文件格式(二)

一、简介 本篇章主要PE文件组成部分中使用的结构体&#xff1b;根据结构体的成员变量去了解各个字节的含义。&#xff08;ps:我们依旧以”cmd.exe“为例展开解析&#xff1b;) 二、DOS Header 1、结构体&#xff1a;IMAGE_DOS_HEADER IMAGE_DOS_HEADER结构体的背景是为了兼…

忘记7-zip文件7-zip文件,还可以解压zip文件吗?

文件压缩与解压已成为我们日常处理数据和存储信息的常规操作。7-Zip&#xff0c;作为一款开源且功能强大的文件压缩工具&#xff0c;凭借其高压缩率、支持多种格式以及免费使用的特点&#xff0c;赢得了广大用户的青睐。然而&#xff0c;出于保护文件内容安全的考虑&#xff0c…

基于NVIDIA NIM平台—生成属于自己的DIY食谱

目录 一、介绍NVIDIA NIM平台 二、生成DIY食谱Demo 三、小结 一、介绍NVIDIA NIM平台 NVIDIA NIM&#xff08;Nvidia Inference Microservices&#xff09;平台是NVIDIA推出的一个微服务套件&#xff0c;旨在加速生成式AI模型在云端、数据中心和工作站上的部署和使用。以下是…