linux下多路复用模型之Select模型
Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型)
Select模型极其作用:这文章讲述的很好,没必要重述已有的东西,就直接给链接
http://blog.csdn.net/turkeyzhou/article/details/8609360
我的理解:
1 /* According to POSIX.1-2001 */ 2 #include <sys/select.h> 3 4 /* According to earlier standards */ 5 #include <sys/time.h> 6 #include <sys/types.h> 7 #include <unistd.h> 8 9 int select(int nfds, fd_set *readfds, fd_set *writefds, 10 fd_set *exceptfds, struct timeval *timeout); 11 12 void FD_CLR(int fd, fd_set *set); 13 int FD_ISSET(int fd, fd_set *set); 14 void FD_SET(int fd, fd_set *set); 15 void FD_ZERO(fd_set *set);
对于
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);第一个参数 nfds: 第n个文件id的编号 (linux下,一切皆文件) 需要注意的是: nfds = fd+1 (fd 为 FD_SET中的fd)第二个参数: fd_set *readfds 读取文件编号,如果不需要读取的话 可以设置为NULL第三 ,四个参数: 同上第五个参数:为一个定义超时的结构体
1 struct timeval { 2 time_t tv_sec; /* seconds */ 3 suseconds_t tv_usec; /* microseconds */ 4 };
该结构用来设定多少时间为超时 ,比如
struct timeval ss ;ss.tv_sec =3;ss.tv_usec =0; //表示设定为3秒后为超时,select将会返回0
对于下面这几个函数:
1 void FD_CLR(int fd, fd_set *set);
用来清除fd的fd_set ,比如fd为5 ,则表示set集中所有设定等于5的fd_set 都将被清除
1 int FD_ISSET(int fd, fd_set *set);
判断是否set 与fd是否绑定,如果没有绑定,则返回false,如果绑定了则返回True
void FD_SET(int fd, fd_set *set);
将fd值 和set绑定
void FD_ZERO(fd_set *set);
将set集全部清除
简单的例子:
判断是否有数据输入,有则直接打印出来
makefile文件:
1 .SUFFIXES: .o.c 2 CC =gcc 3 SRC = Se_keyboard.c 4 OBJ = $(SRC: .c =.o) 5 BIN = Se_keyboard 6 7 8 .PHONY: start 9 start: $(OBJ) 10 $(CC) -o $(BIN) $(OBJ) 11 .o.c: $(SRC) 12 $(CC) -g -Wall $@ -c $< 13 .PHONY: clean 14 clean: 15 rm -f $(OBJ)
虽然知道这么多,但是还是觉得Select并没有什么作用。
Select一般是和Socket搭配使用,相当于线程池的效果,但是线程池有缺点,详情看这儿:
http://blog.csdn.net/tianmohust/article/details/6677985
http://blog.csdn.net/xifeijian/article/details/17385831
关于Select的原理图:
首先来看下一对一的socket的c/s模式
关于socket的一对一的详解
http://www.cnblogs.com/gongxijun/p/4592864.html
看完这个之后,我们现在可以来看看这个图:
下面为举例:
服务器创建一个socket并bind绑定一个本机地址和设定一个端口,然后进入listen监听状态。采用select模型而非传统apache模型(ppc)或者tpc模型 。 不过Select模型就是有这样一个特点
一般我们default默认的SOMAXCONN为128 当然我们可以另外取一个设定(下面我们设定的是2048)作为最大连接数,虽然可以设置更大,但是缺点是,select模型是一个轮询模式,就是每一个都需要遍历一边所有的链接的fd
查看是否在fd_set集合中,这样,当SOMAXCONN取值非常大时,对于每一个客户端,访问时间都会延迟一点点,这样就是效率不是特别高!
下面是一个简单的多路复用的网络并发Select模型
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<unistd.h> 5 #include<netinet/in.h> 6 #include<netinet/ip.h> 7 #include<sys/socket.h> 8 #include<sys/types.h> 9 #include<sys/time.h> 10 #include<arpa/inet.h> 11 #include<sys/select.h> 12 #include<assert.h> 13 14 #ifndef EXIT_SUCCESS 15 #define EXIT_SUCCESS 0 16 #endif 17 18 #ifndef EXIT_FAILURE 19 #define EXIT_FAILURE -1 20 #endif 21 22 #define Max_connect 2048 //usually is SOMAXCONN =128 ,can be change 23 24 #define maxn 1024 25 #define Port 5567 26 #define Ser_addr "192.168.132.128" 27 28 #define ERROR_EXIT( inf ) \ 29 do{ \ 30 perror( inf ); \ 31 printf("it happened in %d \n", __LINE__); \ 32 exit(-1); \ 33 }while(0); 34 35 #define Waring( inf ) \ 36 do{ \ 37 perror( inf ); \ 38 printf("it happened in %d \n", __LINE__); \ 39 }while(0); 40 41 42 int fds[Max_connect]; 43 int cnt = 1; 44 45 void 46 print (int fd, const char *str) 47 { 48 assert (str != NULL); 49 printf ("the fd is %d \n", fd); 50 puts (str); 51 } 52 53 int 54 main (int argv, char *argc[]) 55 { 56 57 int ser_sfd = -1, i; 58 struct sockaddr_in ser_addr; 59 struct sockaddr_in client_addr; 60 int setfd = 0, optval, maxsockfd; 61 62 char rebuf[maxn], wbuf[maxn]; 63 64 // build a socket with ipv4 ans tcp 65 66 if ((ser_sfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 67 ERROR_EXIT ("socket...!"); 68 69 // set the type socket 70 /* 71 level ={ SOL_SOCKET ,IPPROTO_TCP} 72 setsockopt is to cancle the jiangsi process 73 */ 74 75 printf ("ser_sfd = %d \n", ser_sfd); 76 if (setsockopt (ser_sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) 77 < 0) 78 ERROR_EXIT ("setsockopt...!"); 79 80 memset (&client_addr, 0, sizeof (client_addr)); 81 memset (&ser_addr, 0, sizeof (ser_addr)); 82 ser_addr.sin_family = AF_INET; 83 ser_addr.sin_port = htons (Port); 84 ser_addr.sin_addr.s_addr = htonl (INADDR_ANY); 85 86 if (bind (ser_sfd, (struct sockaddr *) &ser_addr, sizeof (ser_addr)) < 0) 87 ERROR_EXIT ("bind..!"); 88 89 if (listen (ser_sfd, Max_connect) < 0) 90 ERROR_EXIT ("listen...!"); 91 92 //user the select moduel 93 memset (fds, 0, sizeof (fds)); 94 fd_set fdset, wfd; 95 maxsockfd = ser_sfd; //max socket fd 96 97 struct timeval tout; 98 99 tout.tv_sec = 15; 100 tout.tv_usec = 0; 101 102 103 while (1) 104 { 105 106 FD_ZERO (&fdset); //clear 107 //FD_ZERO (&wfd); 108 109 FD_SET (ser_sfd, &fdset); //bind 110 //FD_SET (ser_sfd, &wfd); 111 112 struct timeval tout; 113 114 tout.tv_sec = 15; 115 tout.tv_usec = 0; 116 117 118 for (i = 0; i < cnt; i++) 119 { 120 if (fds[i] != 0) 121 FD_SET (fds[i], &fdset); 122 } 123 124 int tag = select (maxsockfd + 1, &fdset, NULL, NULL, &tout); 125 126 if (tag == 0) 127 { 128 Waring ("select wait timeout !"); 129 continue; 130 } 131 else if (tag == -1) 132 ERROR_EXIT ("Error select ...!"); 133 134 //lunxun select 135 for (i = 0; i < cnt; i++) 136 { 137 138 if (FD_ISSET (fds[i], &fdset)) 139 { 140 141 int len = recv (fds[i], rebuf, sizeof (rebuf), 0); 142 if (len <= 0) 143 { 144 145 printf ("%d: \n", fds[i]); 146 close (fds[i]); 147 FD_CLR (fds[i], &fdset); 148 Waring ("client is closed !"); 149 continue; 150 } 151 152 printf ("the client_ip : %s\n", 153 inet_ntoa (client_addr.sin_addr)); 154 155 print (fds[i], rebuf); 156 157 send (fds[i], rebuf, sizeof (rebuf), 0); //hui she 158 memset (rebuf, 0, sizeof (rebuf)); 159 } 160 } 161 //if have a new connect happened 162 // memset(&client_addr , 0 ,sizeof(client_addr)); 163 if (FD_ISSET (ser_sfd, &fdset)) 164 { 165 // memset(&client_addr , 0 ,sizeof(client_addr)); 166 int acplen = sizeof (client_addr); 167 int acp = accept (ser_sfd, (struct sockaddr *) &client_addr, 168 &acplen); 169 170 printf ("accept return acp=%d \n", acp); 171 172 if (acp < 0) 173 { 174 175 Waring ("waring accept acp<=0!"); 176 continue; 177 } 178 //add to arr 179 if (cnt < maxn) 180 fds[cnt++] = acp; 181 else 182 { 183 ERROR_EXIT ("cnt>maxn"); 184 } 185 if (acp > maxsockfd) 186 maxsockfd = acp; 187 } 188 } 189 190 for (i = 0; i < cnt; i++) 191 { 192 close (fds[i]); 193 } 194 195 return EXIT_SUCCESS; 196 }
makefile文件:
1 .SUFFIXES: .o.c 2 CC =gcc 3 SRC = server.c 4 OBJ = $(SRC: .c =.o) 5 BIN = Sez_Server 6 7 8 .PHONY: start 9 start: $(OBJ) 10 $(CC) -o $(BIN) $(OBJ) 11 .o.c: $(SRC) 12 $(CC) -g -Wall $@ -c $< 13 .PHONY: clean 14 clean: 15 rm -f $(OBJ)
客户端:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<netinet/in.h> 5 #include<arpa/inet.h> 6 #include<sys/socket.h> 7 #include<sys/types.h> 8 #include<assert.h> 9 #include<unistd.h> 10 #ifndef EXIT_FAILURE 11 #define EXIT_FAILURE -1 //exit failure 12 #endif 13 #ifndef EXIT_SUCCESS 14 #define EXIT_SUCCESS 0 // exit sucessful 15 #endif 16 17 #define Port 5567 18 #define IPADDR "192.168.132.128" 19 #define maxn 1024 20 21 #define ERROR_EXIT( inf ) \ 22 do{ \ 23 perror( inf ); \ 24 printf("it's happened in %d \n",__LINE__); \ 25 }while(0) ; 26 27 28 //use the function to connect the server !! 29 30 31 int 32 main (int argv, char *argc[]) 33 { 34 35 int sfd = -1; 36 char rbuf[maxn], wbuf[maxn]; 37 // int sfd=-1 ; //socket_fd 38 int confd = -1; //connect_fd 39 struct sockaddr_in soaddr; 40 if ((sfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 41 { 42 ERROR_EXIT ("socket"); 43 return EXIT_FAILURE; 44 } 45 46 //memset a struct 47 memset (&soaddr, 0, sizeof (soaddr)); 48 49 //int the struct sockaddr_in 50 51 soaddr.sin_family = AF_INET; 52 soaddr.sin_port = htons (Port); 53 soaddr.sin_addr.s_addr = inet_addr (IPADDR); 54 55 if ((confd = 56 connect (sfd, (struct sockadrr *) &soaddr, sizeof (soaddr))) < 0) 57 { 58 ERROR_EXIT ("connect"); 59 return EXIT_FAILURE; 60 } 61 62 printf ("connect is sucessful !\n"); 63 64 while (fgets (wbuf, sizeof (rbuf), stdin) != NULL) 65 { 66 write (sfd, wbuf, strlen (wbuf)); 67 read (sfd, rbuf, sizeof (rbuf)); 68 fputs (rbuf, stdout); 69 } 70 71 close (sfd); 72 close (confd); 73 return EXIT_SUCCESS; 74 }
makefile文件:
1 .SUFFIXES: .o.c 2 CC =gcc 3 SRC = client.c 4 OBJ = $(SRC: .c =.o) 5 BIN = Se_client 6 7 8 .PHONY: start 9 start: $(OBJ) 10 $(CC) -o $(BIN) $(OBJ) 11 .o.c: $(SRC) 12 $(CC) -g -Wall $@ -c $< 13 .PHONY: clean 14 clean: 15 rm -f $(OBJ)
效果图:
linux下多路复用模型之Select模型相关推荐
- Linux 下的五种 IO 模型
Linux 下的五种 IO 模型 来源:decaywood's Blog 概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2 ...
- linux下的五种io模型,Linux下的五种IO模型
Java中提供的IO有关的API,在文件处理的时候,其实依赖操作系统层面的IO操作实现的(关于Java对IO的三种封装,可见我的另一篇博客) 开门见山,Linux下的如中IO模型:阻塞IO模型,非阻塞 ...
- linux 网络io命令详解,Linux下五种网络IO模型详解
本文我们主要来了解一下Unix/Linux下5种网络IO模型:blocking IO, nonblocking IO, IO multiplexing, signal driven IO, async ...
- linux 进程sockfd fork,Linux下多进程服务端客户端模型一(单进程与多进程模型)...
本文将会简单介绍Linux下如何利用C库函数与系统调用编写一个完整的.初级可用的C-S模型. 一.基本模型: 1.1 首先服务器调用socket()函数建立一个套接字,然后bind()端口,开始l ...
- LinuxI/O多路复用转接服务器——select模型实现
LinuxI/O多路复用转接服务器--select模型实现 select函数 函数原型 参数和返回值 fd_set结构体 位操作函数 select实现实现I/O多路复用服务器 实现流程 程序实现 服务 ...
- epoll模型与select模型的区别(宿管大妈的例子)
Nginx --->epoll模型 Apache --->select模型 处理大量连接的读写时,Apache所采用的select网络I/O模型比较低,用两个通俗的比喻来解释二者的区别: ...
- [Linux网络编程]高并发-Select模型
概要介绍 一般情况下,处理socket通信一个线程或者进程在处理读写的时候要么阻塞在那一直等要么非阻塞然后过会查看是否可读可写,这样会浪费大量的资源,假如需要对多个套接字进行处理读写那么得开很多个线程 ...
- Linux下多路复用IO接口epoll/select/poll的区别
select比epoll效率差的原因:select是轮询,epoll是触发式的,所以效率高. Select: 1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认 ...
- Linux下多进程服务端客户端模型二(粘包问题与一种解决方法)
一.Linux发送网络消息的过程 (1) 应用程序调用write()将消息发送到内核中 ( 2)内核中的缓存达到了固定长度数据后,一般是SO_SNDBUF,将发送到TCP协议层 (3)IP层从TCP层 ...
最新文章
- Xamarin.Android模拟器提示HAX kernel module is not Installed
- 【RecyclerView】 六、RecyclerView.ItemDecoration 条目装饰 ( 简介 | onDraw | onDrawOver | getItemOffsets )
- MongoDB数据库的下载与Python交互
- python post请求 415_接收错误415:使用REST API发送GET请求时不支持媒体类型
- .NET Core Run On Docker By Kubernetes 系列文章汇总
- python刷题相关资料汇总(二)
- windows下杀死关不掉的进程
- PMP学习笔记 零 启动
- 安卓模拟器安装教程_[教程]安卓手机如何安装百度输入法五笔字根皮肤[教程]...
- Halcon学习笔记——摄像机标定(1)
- 显示器间歇性黑屏问题排查
- 好记性不如烂笔头,要保持学习
- Java 图形界面(满天星星)
- 增长模型拆解:分享有礼裂变玩法的底层逻辑与细节设计
- 堪比巨著:饿了么交易系统5年演化血泪史
- (一)MQTT+阿里云实现设备>云,云>设备之间的通信。
- 解决虚拟机ubuntu20.04不能连外网问题
- 鱼和熊掌兼得——解密阿里云PCDN如何实现高质量低价格
- R计算两列数据的相关系数_使用R语言中的corrplot来绘制相关系数矩阵热图
- 关于CentOS7搭建ELK集群遇到的问题及解决办法
热门文章
- 草履虫纳米机器人_激光驱动的机器人大军!Nature:机器人尺寸小于 0.1 毫米,4 英寸晶圆可容纳 100 万个...
- c语言定义函数insert,c语言编写函数insert(char s1[ ],char s2[ ],int pos),实现在字符串s1中的指定位置pos处插入字符串s2。...
- h2 mysql 差别_h2内存数据库和mysql数据库的区别
- 安卓 spinner下拉框 做模糊查询_如何用一张图来做全年/去年的部门离职率动态对比...
- 1.我和python的第一次亲密接触
- 【c++】22. STL容器的底层实现详解
- 【Tools】git操作总结
- Programming Computer Vision with Python (学习笔记三)
- Python、Lua和Ruby比较——脚本语言大P.K.
- 高等数学:第十章 曲线积分与曲面积分(3)高斯共识、通量、散度、斯托克斯共识、环流量、旋度