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集全部清除

简单的例子:

判断是否有数据输入,有则直接打印出来

View Code

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.  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模型相关推荐

  1. Linux 下的五种 IO 模型

    Linux 下的五种 IO 模型 来源:decaywood's Blog 概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2 ...

  2. linux下的五种io模型,Linux下的五种IO模型

    Java中提供的IO有关的API,在文件处理的时候,其实依赖操作系统层面的IO操作实现的(关于Java对IO的三种封装,可见我的另一篇博客) 开门见山,Linux下的如中IO模型:阻塞IO模型,非阻塞 ...

  3. linux 网络io命令详解,Linux下五种网络IO模型详解

    本文我们主要来了解一下Unix/Linux下5种网络IO模型:blocking IO, nonblocking IO, IO multiplexing, signal driven IO, async ...

  4. linux 进程sockfd fork,Linux下多进程服务端客户端模型一(单进程与多进程模型)...

    本文将会简单介绍Linux下如何利用C库函数与系统调用编写一个完整的.初级可用的C-S模型. 一.基本模型: 1.1   首先服务器调用socket()函数建立一个套接字,然后bind()端口,开始l ...

  5. LinuxI/O多路复用转接服务器——select模型实现

    LinuxI/O多路复用转接服务器--select模型实现 select函数 函数原型 参数和返回值 fd_set结构体 位操作函数 select实现实现I/O多路复用服务器 实现流程 程序实现 服务 ...

  6. epoll模型与select模型的区别(宿管大妈的例子)

    Nginx  --->epoll模型 Apache --->select模型 处理大量连接的读写时,Apache所采用的select网络I/O模型比较低,用两个通俗的比喻来解释二者的区别: ...

  7. [Linux网络编程]高并发-Select模型

    概要介绍 一般情况下,处理socket通信一个线程或者进程在处理读写的时候要么阻塞在那一直等要么非阻塞然后过会查看是否可读可写,这样会浪费大量的资源,假如需要对多个套接字进行处理读写那么得开很多个线程 ...

  8. Linux下多路复用IO接口epoll/select/poll的区别

    select比epoll效率差的原因:select是轮询,epoll是触发式的,所以效率高. Select: 1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认 ...

  9. Linux下多进程服务端客户端模型二(粘包问题与一种解决方法)

    一.Linux发送网络消息的过程 (1) 应用程序调用write()将消息发送到内核中 ( 2)内核中的缓存达到了固定长度数据后,一般是SO_SNDBUF,将发送到TCP协议层 (3)IP层从TCP层 ...

最新文章

  1. Xamarin.Android模拟器提示HAX kernel module is not Installed
  2. 【RecyclerView】 六、RecyclerView.ItemDecoration 条目装饰 ( 简介 | onDraw | onDrawOver | getItemOffsets )
  3. MongoDB数据库的下载与Python交互
  4. python post请求 415_接收错误415:使用REST API发送GET请求时不支持媒体类型
  5. .NET Core Run On Docker By Kubernetes 系列文章汇总
  6. python刷题相关资料汇总(二)
  7. windows下杀死关不掉的进程
  8. PMP学习笔记 零 启动
  9. 安卓模拟器安装教程_[教程]安卓手机如何安装百度输入法五笔字根皮肤[教程]...
  10. Halcon学习笔记——摄像机标定(1)
  11. 显示器间歇性黑屏问题排查
  12. 好记性不如烂笔头,要保持学习
  13. Java 图形界面(满天星星)
  14. 增长模型拆解:分享有礼裂变玩法的底层逻辑与细节设计
  15. 堪比巨著:饿了么交易系统5年演化血泪史
  16. (一)MQTT+阿里云实现设备>云,云>设备之间的通信。
  17. 解决虚拟机ubuntu20.04不能连外网问题
  18. 鱼和熊掌兼得——解密阿里云PCDN如何实现高质量低价格
  19. R计算两列数据的相关系数_使用R语言中的corrplot来绘制相关系数矩阵热图
  20. 关于CentOS7搭建ELK集群遇到的问题及解决办法

热门文章

  1. 草履虫纳米机器人_激光驱动的机器人大军!Nature:机器人尺寸小于 0.1 毫米,4 英寸晶圆可容纳 100 万个...
  2. c语言定义函数insert,c语言编写函数insert(char s1[ ],char s2[ ],int pos),实现在字符串s1中的指定位置pos处插入字符串s2。...
  3. h2 mysql 差别_h2内存数据库和mysql数据库的区别
  4. 安卓 spinner下拉框 做模糊查询_如何用一张图来做全年/去年的部门离职率动态对比...
  5. 1.我和python的第一次亲密接触
  6. 【c++】22. STL容器的底层实现详解
  7. 【Tools】git操作总结
  8. Programming Computer Vision with Python (学习笔记三)
  9. Python、Lua和Ruby比较——脚本语言大P.K.
  10. 高等数学:第十章 曲线积分与曲面积分(3)高斯共识、通量、散度、斯托克斯共识、环流量、旋度