多路复用并发模型  -- select

#include<sys/select.h>

#include<sys/time.h>

int select(int maxfd,  fd_set *readset, fd_set *writeset,  fd_set *exceptset,  struct timeval *timeout)

maxfd    监控的套接字最大值 + 1

readset  集合中任意描述字准备好读,则返回

writeset  集合中任意描述字准备好写,则返回

exceptset 集合中任意描述字有异常等待处理,则返回

timeout     超时则返回(NULL 则一直等待,0 则立即返回)

返回值 =0 超时, 返回值<0 错误,返回值>0正常

多路复用并发模型 -- select

FD_ZERO(fd_set  *fdset)

清空描述符集合

FD_SET(int fd,  fd_set *fdset)

增加fd 到集合中, 事实上就是把某个bit位置位

FD_CLR(int fd,  fd_set *fdset)

从集合中清除fd, 事实上就是把某个bit位清除置位

int  FD_ISSET(int fd,  fd_set  *fdset)

描述字是否准备好

多路复用并发模型  -- select

优点:

通过IO复用,支持交互式输入

通过IO复用,可以同时监听 UDP 和 TCP

相比比多线程, 系统开销大大减少,

缺点:

每次调用 select 都需要把fd集合从用户态拷贝到内核态,fd很多时开销很大

调用 select 需要内核遍历 fd, fd 很多时开销很大

select 支持文件描述符监视有数量限制,默认 1024

服务器端代码:

#include<stdio.h>
#include<unistd.h>
#include<string.h> #include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h> #include<sys/select.h>
#include<sys/time.h> #define SRV_PORT 0xabcd
#define MAX_CONN 3 void RcvMsg(int fds[], int index, int *pnConn)
{
char szBuf[1024] = {0};
int iRet; iRet = read(fds[index], szBuf, 1024);
if (iRet < 0)
{
perror("Fail to read!");
}
else if (iRet == 0)
{
//disconnect. remove fd from fds
printf("[%d]Disconnect...\n", fds[index]);
close(fds[index]); int j;
for (j=index; j < *pnConn - 1; j++)
{
fds[j] = fds[j+1];
}
(*pnConn)--;
}
else
{
printf("[%d]Recv:%s\n", fds[index], szBuf);
} return;
} void TcpServer()
{
int fd;
int iRet;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr); fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
perror("Fail to socket!");
return;
} addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SRV_PORT); iRet = bind(fd, (struct sockaddr*)&addr, addrlen);
if (iRet)
{
perror("Fail to bind!");
close(fd);
return;
} iRet = listen(fd, 100);
if (iRet)
{
perror("Fail to listen!");
close(fd);
return;
} fd_set fdset;
int maxfd = fd;
int fds[MAX_CONN]; //client fd;
int nConn = 0; //client fd num.
int i;
int clientfd;
struct sockaddr_in srcaddr;
char szMsg[100]; while(1)
{
FD_ZERO(&fdset);
FD_SET(fd, &fdset); for (i=0; i<nConn; i++)
{
FD_SET(fds[i], &fdset);//add client fd to fdset for monitor
} fprintf(stderr, "Send:");
scanf("%s", szMsg);
for (i=0; i<nConn; i++)
{
write(fds[i], szMsg, strlen(szMsg));
} iRet = select(maxfd+1, &fdset, NULL, NULL, NULL);
if (iRet < 0)
{
perror("Fail to select!");
break;
}
else if (iRet == 0)
{
//timeout
}
else
{
if (FD_ISSET(fd, &fdset))
{
clientfd = accept(fd, (struct sockaddr*)&srcaddr, &addrlen);
if (clientfd < 0)
{
perror("Fail to accept!");
break;
}
if (nConn == MAX_CONN)
{
char szTip[] = "Over connect, please wait...";
write(clientfd, szTip, sizeof(szTip));
printf("Connect over!\n");
close(clientfd);
}
else
{
char szTip[] = "Welcome!";
write(clientfd, szTip, sizeof(szTip)); printf("[%d]New connection form %s:%d\n", clientfd,
inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port)); fds[nConn] = clientfd;
nConn++; if (clientfd > maxfd)
{
maxfd = clientfd;
}
}
} for (i=0; i<nConn; i++)
{
if (FD_ISSET(fds[i], &fdset))
{
RcvMsg(fds, i, &nConn);
}
} }
} close(fd);
} int main()
{
TcpServer(); return 0;
}

  

31网络通信之Select模型的更多相关文章

  1. 基于Select模型通信程序的编写,编译和执行

    任务目标 编写Win32程序模拟实现基于Select模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递.客户端向服务器端发送"计算从1到100的奇数和",服务 ...

  2. 基于Select模型的Windows TCP服务端和客户端程序示例

    最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...

  3. 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.

    说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...

  4. windows socket编程select模型使用

    int select(         int nfds,            //忽略         fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性       ...

  5. socket编程的select模型

    在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...

  6. linux下多路复用模型之Select模型

    Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...

  7. 比较一下Linux下的Epoll模型和select模型的区别

    一. select 模型(apache的常用) 1. 最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Sel ...

  8. Select模型及tcp select模型

    参考:http://m.blog.csdn.net/article/details?id=51420015 一.套接字模式 套接字模式简单的决定了操作套接字时,Winsock函数是如何运转的.Wins ...

  9. 基于select模型的udp客户端实现超时机制

    参考:http://www.cnblogs.com/chenshuyi/p/3539949.html 多路选择I/O — select模型 其思想在于使用一个集合,该集合中包含需要进行读写的fd,通过 ...

随机推荐

  1. 转:ORACLE 中ROWNUM用法总结!

    oracle 分页查询语句:select * from (select u.*,rownum r from (select * from userifno) u where rownum<大值) ...

  2. 转: jquery中ajax回调函数使用this

    原文地址:jquery中ajax回调函数使用this 写ajax请求的时候success中代码老是不能正常执行,找了半天原因.代码如下 $.ajax({type: 'GET', url: " ...

  3. Aop的基本介绍

    基本概念 通知  就是你想要的功能,也就是我们常说的安全.事物.日志等.先定义好这些,然后再想用的地方用一下.包含Aspect的一段处理代码 注意:其实这些功能(通知)并不是我们业务逻辑所必须的,只是 ...

  4. Java+selenium 如何定位下拉框select

    场景:需要进行下拉选择定位元素.   一.select菜单       select也是比较常见的,selenium封装了以下方法, 创建select WebElement selector = dr ...

  5. push问题1

    问题: $ git pushTo gitee.com:kekemuyu/xtpole.git ! [rejected] master -> master (fetch first)error: ...

  6. 【PyQt5-Qt Designer】在GUI中使用pyqtgraph绘图库

    pyqtgraph绘图库 1.1 简介: pyqtgraph是Python平台上一种功能强大的2D/3D绘图库,相对于matplotlib库,由于内部实现方式上,使用了高速计算的numpy信号处理库以 ...

  7. Eclipse设置注释模板和工作空间背景色为豆沙绿

    Eclipse Version: Photon Release (4.8.0). 首先上图,根据图上的步骤即可完成注释模板的设置. 1 如何设置eclipse注释模板的日期格式 在eclipse的 P ...

  8. jenkins 下载和安装

    jenkins 下载和安装 地址:http://jenkins.io/download/ 下载完成后,点击安装,安装完会发现电脑里多了个jenkins文件夹,打开发现 jenkins.war, 然后点 ...

  9. vue获取地址栏传过来的参数VS原生js获取地址栏的参数

    Vue的方式 Vue的 query方式 ①this.$route.query.companyId ( companyId 为参数的名称 是$route 不是 $router) Vue的 params方 ...

  10. ubuntu上编译linux内核

    Linux 编译:1,首先解压缩内核.2,make     ARCH=arm      CROSS_COMPILE=arm-xilinx-linux-gnueabi-       digilent_z ...