Linux网络编程---多进/线程并发服务器

一、多进程并发服务器

实现一个服务器可以连接多个客户端,每当accept函数等待到客户端进行连接时 就创建一个子进程

思路分析:

核心思路:让accept循环阻塞等待客户端,每当有客户端连接时就fork子进程,让子进程去和客户端进行通信,父进程用于监听并使用信号捕捉回收子进程(子进程关闭用于监听的套接字lfd,父进程关闭用于通信的cfd) 

服务端server.c代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<strings.h>
#include<errno.h>
#include<pthread.h>
#include<signal.h>
#include<sys/wait.h>#define SERV_PORT 9527void sys_err(const char *str)
{perror(str);exit(1);
}void catch_child(int signum)
{while(waitpid(0,NULL,WNOHANG) > 0);return ;
}int main(int argc,char *argv[])
{int lfd = 0,cfd = 0;pid_t pid;int ret;char buf[BUFSIZ],client_IP[1024];//4096struct sockaddr_in serv_addr,clit_addr;socklen_t clit_addr_len;bzero(&serv_addr,sizeof(serv_addr));//将地址结构清零serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);lfd = socket(AF_INET,SOCK_STREAM,0);if (lfd == -1){sys_err("socket errno");}bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));listen(lfd,128);clit_addr_len = sizeof(clit_addr);while(1){cfd = accept(lfd,(struct sockaddr *)&clit_addr,&clit_addr_len);if (cfd == -1){sys_err("accept error");         }printf("client ip is:%s port:%d\n",inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),ntohs(clit_addr.sin_port));pid = fork();if (pid < 0){sys_err("fork error");}else if (pid == 0){close(lfd);break;}else{struct sigaction act;act.sa_handler = catch_child;sigemptyset(&(act.sa_mask));act.sa_flags = 0;ret = sigaction(SIGCHLD,&act,NULL);if (ret != 0){sys_err("sigaction error");}close(cfd);continue;}}if (pid == 0){for(;;){ret = read(cfd,buf,sizeof(buf));if (ret == 0){close(cfd);exit(1);}for (int i = 0;i<ret;i++){buf[i] = toupper(buf[i]);}write(cfd,buf,ret);write(STDOUT_FILENO,buf,ret);}}return 0;
}

一个服务端三个客户端执行多进程服务器并发输出如下: 

补充:

二、多线程并发服务器: 

思路分析:

核心思路:设置监听循环由主线程阻塞等待客户端连接,每当接受到新的客户端连接时,主线程会创建一个新的子线程来处理与该客户端的通信,而主线程继续执行监听循环等待其他客户端(主线程专注于接受新连接,子线程专注于处理客户端请求)

 服务端server.c代码如下:

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>#include "wrap.h"#define MAXLINE 8192
#define SERV_PORT 8000struct s_info {       //定义一个结构体, 将地址结构跟cfd捆绑struct sockaddr_in cliaddr;int connfd;
};void *do_work(void *arg)
{int n,i;struct s_info *ts = (struct s_info*)arg;char buf[MAXLINE];char str[INET_ADDRSTRLEN];      //#define INET_ADDRSTRLEN 16  可用"[+d"查看while (1) {n = Read(ts->connfd, buf, MAXLINE);  //读客户端if (n == 0) {printf("the client %d closed...\n", ts->connfd);break;                           //跳出循环,关闭cfd}printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),ntohs((*ts).cliaddr.sin_port));  //打印客户端信息(IP/PORT)for (i = 0; i < n; i++) buf[i] = toupper(buf[i]);            //小写-->大写Write(STDOUT_FILENO, buf, n);           //写出至屏幕Write(ts->connfd, buf, n);              //回写给客户端}Close(ts->connfd);return (void *)0;            //pthread_exit(0);
}int main(void)
{struct sockaddr_in servaddr, cliaddr;socklen_t cliaddr_len;int listenfd, connfd;pthread_t tid;struct s_info ts[256];      //创建结构体数组.int i = 0;listenfd = Socket(AF_INET, SOCK_STREAM, 0);        //创建一个socket, 得到lfdbzero(&servaddr, sizeof(servaddr));               //地址结构清零servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);     //指定本地任意IPservaddr.sin_port = htons(SERV_PORT);             //指定端口号 Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));   //绑定Listen(listenfd, 128);             //设置同一时刻链接服务器上限数printf("Accepting client connect ...\n");while (1) {cliaddr_len = sizeof(cliaddr);connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //阻塞监听客户端链接请求ts[i].cliaddr = cliaddr;    //把文件描述符和客户端地地址结构组织到一个结构体变量中ts[i].connfd = connfd;pthread_create(&tid, NULL, do_work, (void*)&ts[i]);//表结构体变量作为参数传递到子线程pthread_detach(tid);                //子线程分离,防止僵线程产生.i++;}return 0;
}

执行输出如下: 

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

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

相关文章

怎么用PHP语言实现远程控制电器

怎么用PHP语言实现远程控制电器呢&#xff1f; 本文描述了使用PHP语言调用HTTP接口&#xff0c;实现控制电器&#xff0c;通过控制电器的电源线路来实现电器控制。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能WiFi通断器AC3统…

ubuntu22 部署fastDFS单节点和集群,整合Spring Boot(刚部署成功)

ubuntu22 部署fastDFS单节点和集群 一、先准备1、所需依赖安装2、下载安装包 二、安装FastDFS单节点1、libfastcommon安装1.1、创建软连接 2、安装fastDFS2.1、fastDFS目录简单介绍2.2、创建软连接 3、配置和启动Tracker服务3.1、修改Tracker配置文件3.2、启动Tracker 4、配置和…

IBM SPSS Statistics for Mac v27.0.1中文激活版:强大的数据分析工具

IBM SPSS Statistics for Mac是一款功能强大的数据分析工具&#xff0c;为Mac用户提供了高效、精准的数据分析体验。 IBM SPSS Statistics for Mac v27.0.1中文激活版下载 该软件拥有丰富的统计分析功能&#xff0c;无论是描述性统计、推论性统计&#xff0c;还是高级的多元统计…

金融风控信用评分卡建模(Kaggle give me credit数据集)

1 数据预处理数据 数据来源于Kaggle的Give Me Some Credit&#xff0c;包括25万条个人财务情况的样本数据 1.1 导包读数据 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import RandomForestRegressor import seaborn as …

pyqt设置标签显示图片并设置大小

pyqt设置标签显示图片并设置大小 标签显示图片效果代码 标签显示图片 使用 QPixmap 加载图片进行图片大小设置把图片对象设置到标签上 效果 代码 from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget from PyQt5.QtGui import QPixmap import sys from…

【蓝桥杯2025备赛】素数判断:从O(n^2)到O(n)学习之路

素数判断:从O( n 2 n^2 n2)到O(n)学习之路 背景:每一个初学计算机的人肯定避免不了碰到素数&#xff0c;素数是什么&#xff0c;怎么判断&#xff1f; 素数的概念不难理解:素数即质数&#xff0c;指的是在大于1的自然数中&#xff0c;除了1和它本身不再有其他因数的自然数。 …

比 PSD.js 更强的下一代 PSD 解析器,支持 WebAssembly

比 PSD.js 更强的下一代 PSD 解析器&#xff0c;支持 WebAssembly 1.什么是 webtoon/ps webtoon/ps 是 Typescript 中轻量级 Adobe Photoshop .psd/.psb 文件解析器&#xff0c;对 Web 浏览器和 NodeJS 环境提供支持&#xff0c;且做到零依赖。 Fast zero-dependency PSD par…

openWebUI+ollamawindows+不用docker+webLite本地安装

openWebUI & ollama & windows & 不用docker & webLite 本地安装 总结一下安装教程 10核CPU16G内存 两个web框架都可以&#xff0c;先说简单的 ollama-webui-lite(https://github.com/ollama-webui/ollama-webui-lite) 轻量级&#xff0c;只使用nodejs 先装…

【介绍下如何使用CocoaPods】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

模板(二)

文章目录 模板&#xff08;二&#xff09;1 非类型模板参数2. 模板的特化2.1. 概念2.2 函数模板特化2.3 类模板特化2.3.1 全特化2.3.2 偏特化2.3.3 类模板特化应用示例 3 模板的分离编译3.1 什么是分离编译3.2 模板的分离编译3.3 解决方法 4. 模板总结 模板&#xff08;二&…

20.Nacos集群搭建

模拟Nacos三个节点&#xff0c;同一个ip,启动三个不同的端口&#xff1a; 节点 nacos1, 端口&#xff1a;8845 节点 nacos2, 端口&#xff1a;8846 节点 nacos3, 端口&#xff1a;8847 1.搭建数据库&#xff0c;初始化数据库表结构 这里我们以单点的数据库为例 首先新建一…

vue与Spring boot数据交互例子【简单版】

文章目录 什么是Vue&#xff1f;快速体验Vueaxios是什么&#xff1f;向Springboot后端发送数据接收Springboot后端数据小结 什么是Vue&#xff1f; 官网解释&#xff1a;Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上…

黑马微服务课程1

目录 一、GateWay 二、服务调用OpenFeign 三、Sentinel 1. 流量控制&#xff08;限流规则&#xff09; 2. 隔离和降级 2.1 FeignClient整合Sentinel 2.2 线程隔离&#xff08;舱壁模式&#xff09; 2.3 熔断降级 3. 授权规则 3.1 授权规则 3.2 自定义异常结果 4. 规…

功能测试前景揭秘:会被淘汰吗?

在当今快速发展的信息时代&#xff0c;软件已经成为我们工作、学习乃至生活中不可或缺的一部分。随着技术的不断进步和应用的广泛普及&#xff0c;软件测试作为保障软件质量和功能实现的关键步骤&#xff0c;其职业发展路径也受到了广泛的关注。特别是针对功能测试这一细分领域…

T1级,生产环境事故—Shell脚本一键备份K8s的YAML文件

大家好&#xff0c;我叫秋意零。 最近对公司进行日常运维工作时&#xff0c;出现了一个 T1 级别事故。导致公司的“酒云网”APP的无法使用。我和我领导一起搞了一个多小时&#xff0c;业务也停了一个多小时。 起因是&#xff1a;我的部门直系领导&#xff0c;叫我**删除一个 …

计算机视觉 CV 八股分享 [自用](更新中......)

目录 一、深度学习中解决过拟合方法 二、深度学习中解决欠拟合方法 三、梯度消失和梯度爆炸 解决梯度消失的方法 解决梯度爆炸的方法 四、神经网络权重初始化方法 五、梯度下降法 六、BatchNorm 七、归一化方法 八、卷积 九、池化 十、激活函数 十一、预训练 十二…

MemFire解决方案-物联网数据平台解决方案

方案背景 随着各种通讯、传感技术发展&#xff0c;数据通讯成本的急剧下降&#xff0c;数以万亿计的智能设备&#xff08;智能手环、智能电表、智能手机、各种传感器设备等&#xff09;接入网络&#xff0c;并源源不断的产生海量的实时数据。这些海量数据的价值挖掘&#xff0…

【算法基础实验】图论-基于DFS的连通性检测

基于DFS的连通性检测 理论基础 在图论中&#xff0c;连通分量是无向图的一个重要概念&#xff0c;特别是在处理图的结构和解析图的组成时。连通分组件表示图中的一个子图&#xff0c;在这个子图中任意两个顶点都是连通的&#xff0c;即存在一条路径可以从一个顶点到达另一个顶…

【Webgl_glslThreejs】搬运分享shader_飘落心形

来源网站 https://www.shadertoy.com/view/4sccWr效果预览 代码演示 将shadertory上的代码转成了threejs可以直接用的代码&#xff0c;引入文件的material&#xff0c;并在创建mesh或已有物体上使用material即可&#xff0c;使用时请注意uv对齐。 import { DoubleSide, Shad…

深度学习从入门到精通—Transformer

1.绪论介绍 1.1 传统的RNN网络 传统的RNN&#xff08;递归神经网络&#xff09;主要存在以下几个问题&#xff1a; 梯度消失和梯度爆炸&#xff1a;这是RNN最主要的问题。由于序列的长距离依赖&#xff0c;当错误通过层传播时&#xff0c;梯度可以变得非常小&#xff08;消失…