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,通过 ...
随机推荐
- U3d 入门
环境搭建: 1.安装exe; 2.破解 ,百度
- LeetCode 557 Reverse Words in a String III 解题报告
题目要求 Given a string, you need to reverse the order of characters in each word within a sentence whil ...
- Redis分布式锁服务(转)
原文:http://www.cnblogs.com/mushroom/p/4752499.html 概述 在多线程环境下,通常会使用锁来保证有且只有一个线程来操作共享资源.比如: object obj ...
- JavaWeb学习总结——文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- MySQL innodb_flush_method 【转载】
innodb_flush_method这个参数控制着innodb数据文件及redo log的打开.刷写模式,对于这个参数,文档上是这样描述的: 有三个值:fdatasync(默认),O_DSYNC,O ...
- mysql报错Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage
mysql报错Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage 在执行cr ...
- 20170712 SQL Server 日志文件收索
-- 1 日志文件增长过快,未进行任务计划截断备份 造成文件过大199G 左右,而可用空间不足8% -- 2 日志备份之前,需要一次完整备份 再进行截断备份 出现可用空间99% 此时可以选择收索数据库 ...
- Linux系统上传文件与下载文件命令
我们用的服务器都是Linux系统的,如果用的是远程服务器,就需要将我们的代码推送过去,这里可以用到PSCP命令. (一)上传 pscp 本机文件的路径以及文件名 远程主机的用户名@远程主机IP:想要存 ...
- what's the 回撤
什么是“回撤”? “回撤”是个谓语,前面隐含了一个主语.一般来说,没有人说“亏损回撤”的,我们说的“回撤”,通常指“股价回撤”.“市值回撤”.“净值回撤”和“盈利回撤”. “股价回撤”是针对个股的,即 ...
- Python3学习之路~5.6 shutil & zipfile & tarfile模块
高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length])#将文件内容拷贝到另一个文件中,可以部分内容 shutil.copyfile(s ...