31网络通信之Select模型
多路复用并发模型 -- 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模型的更多相关文章
- 基于Select模型通信程序的编写,编译和执行
任务目标 编写Win32程序模拟实现基于Select模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递.客户端向服务器端发送"计算从1到100的奇数和",服务 ...
- 基于Select模型的Windows TCP服务端和客户端程序示例
最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...
- 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.
说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...
- windows socket编程select模型使用
int select( int nfds, //忽略 fd_ser* readfds, //指向一个套接字集合,用来检测其可读性 ...
- socket编程的select模型
在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...
- linux下多路复用模型之Select模型
Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...
- 比较一下Linux下的Epoll模型和select模型的区别
一. select 模型(apache的常用) 1. 最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Sel ...
- Select模型及tcp select模型
参考:http://m.blog.csdn.net/article/details?id=51420015 一.套接字模式 套接字模式简单的决定了操作套接字时,Winsock函数是如何运转的.Wins ...
- 基于select模型的udp客户端实现超时机制
参考:http://www.cnblogs.com/chenshuyi/p/3539949.html 多路选择I/O — select模型 其思想在于使用一个集合,该集合中包含需要进行读写的fd,通过 ...
随机推荐
- git忽略UserInterfaceState.xcuserstate
使用sourceTree, 忽略
- java 数组(二)
public class ArrayDemo{ public static void main(String[] args){ int[] arr = {1,5,3,8,2,9,17,13}; get ...
- linux 内核启动流程分析,移植
分析 linux-2.6.22.6 内核启动流程 移植 linux-3.4.2 到 JZ2440 开发板 Linux内核源码百度云链接: https://pan.baidu.com/s/1m1ymGl ...
- 给予Java初学者的学习路线建议
va学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈每个阶 ...
- SpringBoot静态资源访问
在我们开发Web应用的时候,需要引用大量的js.css.图片等静态资源. 默认配置: Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则: /static ...
- [转载]智能科普:VR、AR、MR的区别
智能科普:VR.AR.MR的区别 http://news.zol.com.cn/553/5534833.html news.zol.com.cn 2015-11-23 16:00 近日, 获得谷歌5亿 ...
- js模拟下拉框
html <label class="selectGroup"> <span class="selectP"></span> ...
- RN无限轮播以及ScrollView的大小调节问题
如果你的ScrollView的大小是全屏,height不能用,这种情况需要给ScrollView添加一个容器View,然后调节容器View的大小 无限轮播这里我使用的是一个第三方的插件react-na ...
- 搭建nginx服务器,虚拟主机,反向代理
1 搭建Nginx服务器 1.1 问题 在IP地址为192.168.10. 5的主机上安装部署Nginx服务,并可以将Nginx服务器升级到更高版本,要求编译时启用如下功能: SSL加密功能 查看服务 ...
- Java中的boxing和unboxing(转)
测试代码: System.out.println(0L == 0);//true System.out.println(((Long)0L).equals(0));//false Integer i1 ...