多路复用并发模型  -- 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. 【PyQt5-Qt Designer】液晶显示屏(QLCDNumber)

    液晶显示屏(QLCDNumber) 总体介绍 QLCDNumber小部件显示一个类似LCD的数字. 它可以显示任何大小的数字.它可以显示十进制,十六进制,八进制或二进制数字.使用display()槽连 ...

  2. oracle按照指定列分组合计group by rollup()

    group by rollup() 按分组合计 select grouping(status),status,owner,object_type,count(*) from dba_objects w ...

  3. oracle的undo表空间

    undo表空间是Oracle特有的概念.undo表空间中会自动分配undo段,这些undo段用来保存事务中的DML语句的undo信息,也就是来保存数据在被修改之前的值.在rollback,实例恢复(回 ...

  4. maven工程中防止mapper.xml文件被漏掉、未加载的方法

    maven工程中防止mapper.xml文件被漏掉.未加载的方法 就是在pom.xml文件中添加以下内容 <!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉. --&g ...

  5. RSA 时序攻击

    RSA的破解从理论上来讲是大数质数分解,可是就是有一些人另辟蹊径,根据你解密的时间长短就能破解你的RSA私钥. 举一个不恰当但是比较容易理解的例子: 密文0101 私钥0110 明文0100 问题的关 ...

  6. Mysql事务原理介绍

    事务 一个事务会涉及到大量的cpu计算和IO操作,这些操作被打包成一个执行单元,要么同时都完成,要么同时都不完成. 事务是一组原子性的sql命令或者说是一个独立的工作单元,如果数据库引擎能够成功的对数 ...

  7. Wi-Fi 协议和数率?

    IEEE 802.11Wi-Fi 协议摘要 协议 频率 信号 最大数据速率 传统 802.11 2.4GHz FHSS 或 DSSS 2Mbps 802.11A 5GHz OFDM 54Mbps 80 ...

  8. .ashx文件与.ashx.cs

    如果项目是“新建网站”,添加的ashx是没有ashx.cs的:如果是新建"asp.net web 应用程序",添加的ashx是有ashx.cs的. 今天做项目测试遇到一个问题,因为 ...

  9. 云服务器--linux系统操作命令以及安装ngnix记录,以及手动部署本地文件

    1.控制台登陆服务器,需要首先知道服务器ip和密码,,命令是 ssh root@1.1.1.1(服务器IP),然后输入密码登入服务器 2.查看linux 版本的系统命令是 cat /etc/redha ...

  10. sqlserver把数据导入mysql

    sqlserver库 navicat逆向表到模型 转换模型为... 选择mysql 建模转换后导出sql 导出sql后,再mysql库中执行该sql(该sql为表结构)执行sql后,使用navicat ...