TCP并发服务器模型

1.阻塞IO

 CPU占用率低,等待资源时将任务挂起,不占用CPU资源,等到拿到资源后继续向下执行

向管道中写入数据

write.c

#include "../head.h"
int main()
{int fd;mkfifo("/tmp/myfifo",0777);char tmpbuff[100]={0};fd=open("/tmp/myfifo",O_WRONLY);if(fd==-1){return -1;}while(1){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);tmpbuff[strlen(tmpbuff)-1]='\0';write(fd,tmpbuff,strlen(tmpbuff));}close(fd);return 0;
}

read.c: 先从终端写入数据,再从管道读入数据,管道必须等终端写入才可以读,第二次循环,终端也必须等第一次循环管道读入数据后才能继续从终端写,互相阻塞

#include "head.h"int main(void)
{int fd = 0;char tmpbuff[4096] = {0};mkfifo("/tmp/myfifo", 0777);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}while (1){memset(tmpbuff, 0, sizeof(tmpbuff));read(fd, tmpbuff, sizeof(tmpbuff));printf("FIFO:%s\n", tmpbuff);memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);printf("STDIN:%s\n", tmpbuff);}close(fd);return 0;
}

2.非阻塞IO 

  能够让任务不阻塞,效率低,因为没有数据时,CPU一直空转

write.c和第一个相同 

read.c:将管道和stdin流都设置为非阻塞属性

#include "../head.h"
int main()
{int fd;ssize_t nsize=0;int flags=0;char tmpbuff[200]={0};char *pret=NULL;mkfifo("/tmp/myfifo",0777);fd=open("/tmp/myfifo",O_RDONLY);if(fd==-1){return -1;}/*获得fd文件描述符的属性*/flags=fcntl(fd,F_GETFL);/*在现有属性中加入非阻塞属性*/flags|=O_NONBLOCK;/*将新属性设置回文件描述符中*/fcntl(fd,F_SETFL,flags);/*设置stdin的属性为非阻塞属性*/flags=fcntl(0,F_GETFL);flags|=O_NONBLOCK;fcntl(0,F_SETFL,flags);while(1){/*从管道中读数据*/memset(tmpbuff,0,sizeof(tmpbuff));nsize=read(fd,tmpbuff,sizeof(tmpbuff));if(nsize>0){printf("FIFO:%s\n",tmpbuff);}/*从终端读数据*/memset(tmpbuff,0,sizeof(tmpbuff));pret=gets(tmpbuff);if(pret!=NULL){printf("STDIN:%s\n",tmpbuff);}}close(fd);return 0;
}

3.异步IO
    将一个文件描述符设定为异步IO,当IO有事件发生时,内核会向用户层发送SIGIO信号提醒用户层处理事件

write.c和第一个相同 

read.c:将管道设定为异步IO,当管道中有数据写入时发送信号,执行处理函数

#include "../head.h"
int fd;
void handler(int signo)
{char tmpbuff[256]={0};memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("FIFO:%s\n",tmpbuff);}  
int main()
{ssize_t nsize=0;int flags=0;char tmpbuff[200]={0};char *pret=NULL;/*当文件描述符有信号发生时(管道写入数据),发送信号通知,执行处理函数*/signal(SIGIO,handler);mkfifo("/tmp/myfifo",0777);fd=open("/tmp/myfifo",O_RDONLY);if(fd==-1){return -1;}/*获得fd文件描述符的属性*/flags=fcntl(fd,F_GETFL);/*将fd设置为异步IO(文件描述符发生可以读的事件,会发送信号通知)*/flags|=O_ASYNC;/*将新属性设置回文件描述符中*/fcntl(fd,F_SETFL,flags);//通知给当前进程fcntl(fd,F_SETOWN,getpid());while(1){memset(tmpbuff,0,sizeof(tmpbuff));pret=gets(tmpbuff);if(pret!=NULL){printf("STDIN:%s\n",tmpbuff);}}close(fd);return 0;
}

4.多路复用IO

  1.select
        监听文件描述符集合,将所有要监听的事件加入集合中,使用select监听所有事件,当集合中有事件发生,  select不再阻塞,同时select会将产生事件的文件描述符留在集合中,而把没有产生事件的文件描述符从集合中踢出,所以留在集合中的文件描述即为产生事件的文件描述符,对其处理即可

        函数接口:
        1.int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
          功能:
            监听文件描述符是否有事件发生
          参数:
            nfds:最大文件描述符的值 + 1 
            readfds:读文件描述符集合
            writefds:写文件描述符集合
            exceptfds:异常文件描述符集合
            timeout:超时时间
          返回值:
            成功返回产生事件的文件描述符个数
            失败返回-1 
            timeout时间到达仍然没有产生的事件返回0 

        void FD_CLR(int fd, fd_set *set);
        功能:将fd从集合中清除
        int  FD_ISSET(int fd, fd_set *set);
        功能:判断fd是否仍在文件描述符集合中
        void FD_SET(int fd, fd_set *set);
        功能:将fd加入文件描述符集合中
        void FD_ZERO(fd_set *set);
        功能:将文件描述符集合清0 

write:与第一个相同 

read.c:当管道或者终端某一个有时间发生时,留下发生事件的那个文件描述符,其余删除,检测哪个文件描述符还在文件描述符集合中,就处理哪个

#include "../head.h"
int fd;int main()
{ssize_t nsize=0;int flags=0;char tmpbuff[200]={0};char *pret=NULL;fd_set rdfds;fd_set tmpfds;int maxfd;int nready=0;mkfifo("/tmp/myfifo",0777);fd=open("/tmp/myfifo",O_RDONLY);if(fd==-1){return -1;}/* 将文件描述符集合清0 */FD_ZERO(&rdfds);FD_SET(fd,&rdfds);/*将stdin加入文件描述符集合中*/FD_SET(0,&rdfds);maxfd=fd;while(1){tmpfds=rdfds;//监听发生事件的文件描述符,将其余文件描述符从文件描述符集合中清除nready=select(maxfd+1,&tmpfds,NULL,NULL,NULL);if(-1==nready){perror("failed to select");return -1;}/*判断fd是否仍在文件描述符集合中*/if(FD_ISSET(fd,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("FIFO:%s\n",tmpbuff);} /*判断stdin是否仍在文件描述符集合中*/if(FD_ISSET(0,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));pret=gets(tmpbuff);if(pret!=NULL){printf("STDIN:%s\n",tmpbuff);}}}close(fd);return 0;
}

 TCP多路复用应用

client向server发送数据,再接收server的回复

client.c

#include "../head.h"
int CreateTcpConnection()
{int sockfd;int ret=0;struct sockaddr_in sendaddr;//创建套接字sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){return -1;}sendaddr.sin_family=AF_INET;sendaddr.sin_port=htons(50000);sendaddr.sin_addr.s_addr=inet_addr("192.168.0.187");//发送连接ret=connect(sockfd,(struct sockaddr *)&sendaddr,sizeof(sendaddr));if(ret==-1){return -1;}return sockfd;
}
int HandleConnection(int sockfd)
{char tmpbuff[1024]={0};static int cnt=0;ssize_t nsize=0;//发送数据sprintf(tmpbuff,"hello world --%d",cnt);nsize=send(sockfd,tmpbuff,strlen(tmpbuff),0);if(nsize==-1){return -1;}cnt++;//接收数据memset(tmpbuff,0,sizeof(tmpbuff));nsize=recv(sockfd,tmpbuff,sizeof(tmpbuff),0);if(nsize==-1){return -1;}else if(nsize==0){return 0;}printf("RECV:%s\n",tmpbuff);return nsize;
}
int main()
{int sockfd;int ret=0;sockfd=CreateTcpConnection();if(sockfd==-1){printf("连接服务器出错\n");return -1;}while(1){ret=HandleConnection(sockfd);if(ret==-1){printf("连接出错\n");break;}else if(ret==0){printf("关闭连接\n");break;}sleep(1);}//关闭套接字close(sockfd);return 0;
}

server.c:监听是否有新的连接请求,如果sockfd产生事件,处理新的请求,并将新的文件描述符加入集合,下一次一起监听,遍历所有已连接客户端,要是某个客户端有事件发生,就执行它的处理函数:接收来自客户端的数据,并回复客户端新拼接的数据

#include "../head.h"
int CreateTcpConnection()
{int sockfd;int ret=0;struct sockaddr_in recvaddr;sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){return -1;}recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(50000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.187");ret=bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(ret==-1){return -1;}ret=listen(sockfd,20);if(ret==-1){return -1;}return sockfd;}
int HandleConnection(int confd)
{char tmpbuff[1024]={0};ssize_t nsize=0;//接收数据并打印nsize=recv(confd,tmpbuff,sizeof(tmpbuff),0);if(nsize==-1){return -1;}else if(nsize==0){return 0;}printf("RECV:%s\n",tmpbuff);
//返回数据sprintf(tmpbuff,"%s--echo",tmpbuff);nsize=send(confd,tmpbuff,strlen(tmpbuff),0);if(nsize==-1){return -1;}return nsize;
}
int main()
{int sockfd;int i=0;int maxfd=0;fd_set rdfds;fd_set tmpfds;int nready=0;int ret=0;int confd;//创建套接字sockfd=CreateTcpConnection();if (-1 == sockfd){printf("创建监听套接字失败\n");return -1;}//将sockfd加入监听集合中FD_ZERO(&rdfds);FD_SET(sockfd,&rdfds);maxfd=sockfd;while(1){//开始监听tmpfds=rdfds;nready=select(maxfd+1,&tmpfds,NULL,NULL,NULL);if(nready==-1){perror("failed to select");return -1;}//  如果sockfd产生事件,处理新的请求,并将新的文件描述符加入集合,下一次一起监听if(FD_ISSET(sockfd,&tmpfds)){confd=accept(sockfd,NULL,NULL);if(confd==-1){FD_CLR(sockfd,&rdfds);close(sockfd);continue;}maxfd=maxfd>confd?maxfd:confd;FD_SET(confd,&rdfds);}//遍历所有已经连接的客户端中是否有事件发生for(i=sockfd+1;i<=maxfd;i++){if(FD_ISSET(i,&tmpfds)){ret=HandleConnection(i);if(ret==-1){printf("连接异常\n");FD_CLR(i,&rdfds);close(i);continue;}else if(ret==0){printf("关闭连接\n");FD_CLR(i,&rdfds);close(i);continue;}}}}close(sockfd);return 0;
}

 运行结果:一个服务器连接两个客户端(可以连接更多的客户端)

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

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

相关文章

三十八、【人工智能】【机器学习】【监督贝叶斯网络(Bayesian Networks)学习】- 算法模型

系列文章目录 第一章 【机器学习】初识机器学习 第二章 【机器学习】【监督学习】- 逻辑回归算法 (Logistic Regression) 第三章 【机器学习】【监督学习】- 支持向量机 (SVM) 第四章【机器学习】【监督学习】- K-近邻算法 (K-NN) 第五章【机器学习】【监督学习】- 决策树…

39_WAF的概念、功能,ModSecurity部署配置、LAMP环境部署、Ubuntu搭建DVWA靶机测试、测试WAF防御、OWASP规则集的部署

一、WAF的概念 WAF&#xff08; Web Application Firewall &#xff09;&#xff0c;即Web应用防火墙 通过执行一系列HTTP/HTTPS&#xff08;应用层的协议&#xff09;的安全策略为Web应用提供保护的一种网络安全产品。增加攻击者的难度和成本&#xff0c;但不是100%安全。工…

halcon的HObject被释放

经过简述 某项目由我统一管理HObject(区域和图像)的释放。发现某区域被系统外部所释放。可能有两种情况&#xff1a;a&#xff0c;区域交给我后&#xff0c;释放了。b&#xff0c;获取我的区域后释放了。 最终证明是第二种情况&#xff0c;证明如下&#xff1a; a&#xff0c;…

Python数据分析:Pandas与NumPy结合,实现高效数值计算,提升数据分析效率的最佳实践

目前小编的借调任务已经完成&#xff0c;借调到其他组完成了自己的工作&#xff0c;有需要的同学可以看下相关的文章&#xff1a;Python&#xff08;Flask&#xff09; React && Golang&#xff08;Gin&#xff09; Vue(Element)&#xff0c;然后小编认为可以回到原来的…

深入探讨 Nginx:安装、配置及优化指南

一、Nginx 概述及编译安装 1、概述 Nginx是一个高性能的开源HTTP和反向代理服务器&#xff0c;同时也是一个IMAP/POP3邮件代理服务器。它最初由Igor Sysoev于2002年开发&#xff0c;并于2004年首次发布。Nginx以其高并发性、低资源消耗和灵活的配置能力而受到广泛关注&#x…

[鹏城杯 2022]简单的php

题目源代码 <?phpshow_source(__FILE__); $code $_GET[code]; if(strlen($code) > 80 or preg_match(/[A-Za-z0-9]|\|"||\ |,|\.|-|\||\/|\\|<|>|\$|\?|\^|&|\|/is,$code)){die( Hello); }else if(; preg_replace(/[^\s\(\)]?\((?R)?\)/, , $code…

网安新声 | 从微软“狂躁许可”漏洞事件看安全新挑战与应对策略

网安加社区【网安新声】栏目&#xff0c;汇聚网络安全领域的权威专家与资深学者&#xff0c;紧跟当下热点安全事件、剖析前沿技术动态及政策导向&#xff0c;以专业视野和前瞻洞察&#xff0c;引领行业共同探讨并应对新挑战的策略与可行路径。 近期&#xff0c;微软披露了一个最…

JSON, YAML, XML, CSV交互可视化

1、jsoncrack https://jsoncrack.com/editor

双亲委派机制的优势与劣势

三次双亲委派机制的破坏

反向代理:定义与核心作用

反向代理&#xff1a;定义与核心作用 一、反向代理的定义二、反向代理的核心作用 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 反向代理&#xff0c;作为网络架构中的重要组件&#xff0c;扮演着关键角色。本文将简洁介绍反向代理的定义及…

整体思想以及取模

前言&#xff1a;一开始由于失误&#xff0c;误以为分数相加取模不能&#xff0c;但是其实是可以取模的 这个题目如果按照一般方法&#xff0c;到达每个节点再进行概率统计&#xff0c;但是不知道为什么只过了百分之十五的测试集 题目地址 附上没过关的代码 #include<bits…

【区块链+商贸零售】预付宝:商家数字经济服务平台 | FISCO BCOS应用案例

预付宝商家数字经济服务平台是人民链在金融领域落地的 一个区块链应用&#xff0c;致力于营造诚信消费环境&#xff0c;专治诸如健 身房老板卷款跑路、充值后餐馆倒闭钱拿不回来等令消费 者头疼不已的行业乱象&#xff0c;让消费者可以放心地预付费。 平台应用FISCO BCOS区块链…

设计模式学习[3]---单一职责原则+开放封闭原则

文章目录 前言1. 单一职责1.1 原理阐述1.2 处理方式 2. 开放-封闭原则2.1 原理阐释2.2 举例说明 总结 前言 小项目写多了&#xff0c;比如一些什么管理系统之类的&#xff0c;在接触大型项目的时候往往会将之前的一些面向过程的写法代入。 比如UI以及逻辑处理都放在一个类里面…

Flutter【01】状态管理

声明式编程 Flutter 应用是 声明式 的&#xff0c;这也就意味着 Flutter 构建的用户界面就是应用的当前状态。 当你的 Flutter 应用的状态发生改变时&#xff08;例如&#xff0c;用户在设置界面中点击了一个开关选项&#xff09;你改变了状态&#xff0c;这将会触发用户界面…

25届科大讯飞飞星计划 AI研究算法工程师 面经

目录 一面/技术面 2024/08/15 &#x1f4cb; 总结&#xff1a; 本来应该是在7月底面试的&#xff0c;但因为有事就拖到了现在&#xff0c;或许是飞星计划里最晚面试的一批&#xff1f;面试官很和蔼&#xff0c;问的问题不算难&#xff0c;总体体验还算不错。 一面/技术面 2024/…

洛谷B3981题解

题目描述 &#xff08;你不需要看懂这张图片&#xff1b;但如果你看懂了&#xff0c;会觉得它很有趣。&#xff09; JavaScript 是一种功能强大且灵活的编程语言&#xff0c;也是现代 Web 开发的三大支柱之一 (另外两个是 HTML 和 CSS)。灵活的 JavaScript 包含“自动类型转换…

Python 数据分析之Numpy学习(一)

Python 数据分析之Numpy学习&#xff08;一&#xff09; 一、Numpy的引入 1.1 矩阵/向量的按位运算 需求&#xff1a;矩阵的按位相加 [0,1,4] [0,1,8] [0,2,12] 1.1.1 利用python实现矩阵/向量的按位运算 # 1.通过列表实现 list1 [0, 1, 4] list2 [0, 1, 8]# 列表使用…

【Linux网络】select函数

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 select函数介绍select函数参数介绍select函数返回值select的工作流程TCP服务器【多路复用版】 select函数介绍 在Linux网络编程中&#xff0c;select 函数是一种非常有用的IO多路复用技术&#xff0…

基于Java和GeoTools的Shapefile矢量数据缩略图生成实践

目录 前言 一、关于GeoTools的图片生成 1、关于GtRenderer 2、关于 图像生成架构 3、流式计算绘制 二、全球空间预览生成实战 1、pom.xml中关于图像生成依赖 2、样式设置及地图资源绑定 3、图片生成绘制 4、图片生成测试 三、成果验证 1、全球范围生成 2、我国的范…