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 bash 命名
git log -p -2 我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新. git diff HEAD git clean -df 恢复到最后一次提交的改动: gi ...
- 安装多个java后,java版本不对
参考资料: https://www.cnblogs.com/Kidezyq/p/5781131.html 主要原因是javac -version是由JAVA_HOME指定的路径中的java版本来决定的 ...
- 【Java】一台服务器配置多个Tomcat
需求缘由 最近接收了一个新的工具业务:ipublish发布系统,刚接手这个业务的时候,发现每次发布新的代码 需要到群里告知大家,我要停服务几分钟,准备更新代码啦.这尼玛 哪个公司都不敢这么牛逼的和用户 ...
- 转:JAVA中解决Filter过滤掉css,js,图片文件等问题
原文链接:https://www.cnblogs.com/ermeng/p/6440966.html public void doFilter(ServletRequest request, Serv ...
- LeetCode 566 Reshape the Matrix 解题报告
题目要求 In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a ...
- 《Mysql 日志结构》
推荐一首歌 - <往后余生>王贰浪 发现自己每天就听这么几首歌 一:慢查询日志 - SQL 完成查询并完成对于锁资源的释放之后,msqld 会将符合条件的SQL写入慢日志.因此慢日志可能和 ...
- HD200703
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inc ...
- 运行Maven工程中修改tomcat端口
Maven 运行:clean tomcat7:run 若需要修改端口,则用clean -Dmaven.tomcat.port=8082 tomcat7:run
- 通过Tesseract实现简单的OCR
Tesseract 简介 Tesseract 的 OCR 引擎最先由 HP 实验室于 1985 年开始研发,至 1995 年时已经成为 OCR 业内最准确的三款识别引擎之一.然而,HP 不久便决定放弃 ...
- 火币网API文档——WebSocket API简介
WebSocket API简介 WebSocket协议是基于TCP的一种新的网络协议.它实现了客户端与服务器之间在单个 tcp 连接上的全双工通信,由服务器主动发送信息给客户端,减少了频繁的身份验证等 ...