在很多比较各种网络模型的文章中,但凡提到select模型时,都会说select受限于轮询的套接字数量,这个
数量也就是系统头文件中定义的FD_SETSIZE值(例如64)。但事实上这个算不上真的限制。 C语言的偏方: 在C语言的世界里存在一个关于结构体的偏门技巧,例如: typedef struct _str_type
{
int _len;
char _s[];
}str_type; str_type用于保存字符串(我只是举例,事实上这个结构体没什么用处),乍看上去str_type只能保存长度为
1的字符串('\0')。但是,通过写下如下的代码,你将突破这个限制: int str_len = ;
str_type *s = (str_type*) malloc( sizeof( str_type ) + str_len - );
//
free( s ); 这个技巧原理很简单,因为_s恰好在结构体尾部,所以可以为其分配一段连续的空间,只要注意指针的使用,
这个就算不上代码上的罪恶。但是这个技巧有个限制,str_type定义的变量必须是被分配在堆上,否则会破
坏堆栈。另外,需要动态增长的成员需要位于结构体的末尾。最后,一个忠告就是,这个是C语言里的技巧,
如果你的结构体包含了C++的东西,这个技巧将不再安全(<Inside the C++ object model>)。 其实select也可以这样做: 事实上,因为select涉及到的fd_set是一个完全满足上述要求的结构体: winsock2.h : typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set; 但是,如果使用了以上技巧来增加fd_array的数量(也就是保存的套接字数量),那么关于fd_set的那些宏可
能就无法使用了,例如FD_SET。 winsock2.h : #define FD_SET(fd, set) do { \
u_int __i; \
for (__i = ; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == (fd)) { \
break; \
} \
} \
if (__i == ((fd_set FAR *)(set))->fd_count) { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
((fd_set FAR *)(set))->fd_array[__i] = (fd); \
((fd_set FAR *)(set))->fd_count++; \
} \
} \
} while() 有点让人眼花缭乱,我鼓励你仔细看,其实很简单。这里有个小技巧,就是他把这些代码放到一个do...while()
里,为什么要这样做,我觉得应该是防止名字污染,也就是防止那个__i变量与你的代码相冲突。可以看出,
FD_SET会将fd_count与FD_SETSIZE相比较,这里主要是防止往fd_array的非法位置写数据。 因为这个宏原理不过如此,所以我们完全可以自己写一个新的版本。例如: #define MY_FD_SET( fd, set, size ) do { \
unsigned int i = ; \
for( i = ; i < ((fd_set*) set)->fd_count; ++ i ) { \
if( ((fd_set*)set)->fd_array[i] == (fd) ) { \
break; \
} \
} \
if( i == ((fd_set*)set)->fd_count ) { \
if( ((fd_set*)set)->fd_count < (size) ) { \
((fd_set*)set)->fd_array[i] = (fd); \
((fd_set*)set)->fd_count ++; \
} \
} \
} while( ) 没什么变化,只是为FD_SET加入一个fd_array的长度参数,宏体也只是将FD_SETSIZE换成这个长度参数。
于是,现在你可以写下这样的代码: unsigned int count = ;
fd_set *read_set = (fd_set*) malloc( sizeof( fd_set ) + sizeof(SOCKET) * (count - FD_SETSIZE ) );
SOCKET s = socket( AF_INET, SOCK_STREAM, );
//
MY_FD_SET( s, read_set, count );
//
free( read_set );
closesocket( s ); 小提下select模型: 这里我不会具体讲select模型,我只稍微提一下。一个典型的select轮询模型为: int r = select( , &read_set, , , &timeout );
if( r < )
{
// select error
} if( r > )
{
for( each sockets )
{
if( FD_ISSET( now_socket, &read_set ) )
{
// this socket can read data
}
}
} 轮询write时也差不多。在Etwork(一个超小型的基本用于练习网络编程的网络库,google yourself)中,作者
的轮询方式则有所不同: // read_set, write_set为采用了上文所述技巧的fd_set类型的指针
int r = select( , read_set, write_set, , &timeout );
// error handling
for( int i = ; i < read_set->fd_count; ++ i )
{
// 轮询所有socket,这里直接采用read_set->fd_array[i] == now_socket判断,而不是FD_ISSET
} for( int i = ; i < write_set->fd_count; ++ i )
{
// 轮询所有socket,检查其whether can write,判断方式同上
} 两种方式的效率从代码上看去似乎都差不多,关键在于,FD_ISSET干了什么?这个宏实际上使用了__WSAFDIsSet
函数,而__WSAFDIsSet做了什么则不知道。也许它会依赖于FD_SETSIZE宏,那么这在我们这里将是不安全的,
所以相比之下,如果我们使用了这个突破FD_SETSIZE的偏方手段,那么也许第二种方式要好些。

其实我就是想看看select模式到底是啥,不知libeventwindows下用的是select还是iocp,select模式怎么突破64啊

select模式的更多相关文章

  1. WinSockets编程(六)select模式

    select模式的思想 创建FD_SET fd_all,并初始化FD_ZERO(&fd_all); Step1  初始时: Step2   加入一个套接字之后,比如FD_SET(sServer ...

  2. WPF InkCanvas EditingMode为Select时 在其选择时各种事件中撤销Select模式的方法

    InkCanvas有多种输入模式. 通过InkCanvasEditingMode来进行对其调整 分别是 None=0// 忽略鼠标和手写笔输入 Ink = 1// 允许用户绘制批注,默认模式.使用鼠标 ...

  3. python 简单搭建非阻塞式单进程,select模式,epoll模式服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...

  4. Select模式和超时

    fd_set rset; FD_ZERO(&rset); int nready; int maxfd; int fd_stdin = fileno(stdin); if(fd_stdin &g ...

  5. select,epool,pool解释

    内容主要来自搜狗实验室技术交流文档, 编写链接数巨大的高负载服务器程序时,经典的多线程模式和select模式都不再适合了.应该采用epool/kqueue/dev_pool来捕获IO事件. ----- ...

  6. [转载] Linux下多路复用IO接口 epoll select poll 的区别

    原地址:http://bbs.linuxpk.com/thread-43628-1-1.html 废话不多说,一下是本人学习nginx 的时候总结的一些资料,比较乱,但看完后细细揣摩一下应该就弄明白区 ...

  7. Winsock IO模型之select模型

    之所以称其为select模型是因为它主要是使用select函数来管理I/O的.这个模型的设计源于UNIX系统,目的是允许那些想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字. int sele ...

  8. socket select模型

    由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不 ...

  9. winsock编程select模型

    winsock编程select模型 网络服务端连接数量过多时,为每一个连接申请一个线程会让机器性能急剧下降(大多说是因为线程在用户态和内核态之间切换会占用大量的CPU时间片).为了解决多线程带来的性能 ...

随机推荐

  1. ORACLE 对用户密码做限制

    1. 查看默认设置 2. PASSWORD_LIFE_TIME 60 --口令的生命周期,超过这段时间口令可能会自动过期,是否过期要看是否设定了PASSWORD_GRACE_TIME PASSWORD ...

  2. 【转】C#异步编程及其同步机制

    C#异步编程及其同步机制 本篇文章涵盖一下几部分内容: 1. 什么是异步编程,为什么会需要异步编程 2. .NET下的异步编程及其发展 3. .NET线程同步机制及线程间数据封送 4. 异步模式 5. ...

  3. php29号小结(隔行换色······)

    1.给表单加样式,可以用css.php与js.js这三种,其中最好用php与js,现在很推广用这种. css3样式隔行换色(table中) tr:nth-child(even){ background ...

  4. Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法

    Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法 java.lang.OutOfMemoryError: Java heap sp ...

  5. javaweb毕业设计

    javaweb毕业设计,管理系统设计,Strut2项目,Springmvc项目,javaweb项目学习. 都是可以运行的,(配数据库和论文),都能提供技术咨询,可以修改.欢迎+扣扣396058587咨 ...

  6. nyoj_t218(Dinner)

    描述 Little A is one member of ACM team. He had just won the gold in World Final. To celebrate, he dec ...

  7. 走出 null 就是空值的误区,以及变量赋值原理

    先放一张图片作为引入: 这里我用了一个示意图作为讲解: 平时,我们写的变量为什么能在我们调用它的时候就能被我们拿到所用,跟存钱罐一样,你往里面存一元大洋,它里面就有一元大洋,那么我们的变量在被我们创建 ...

  8. C++ Vector 动态数组

    Vectors 包含着一系列连续存储的元素,其行为和数组类似.访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线 ...

  9. Windows Phone 8.1开发:如何让ListView下拉加载更多?

    Windows Phone 8.1开发中使用ListView作为数据呈现载体时,经常需要一个下拉(拇指向上滑动)加载更多的交互操作.如何完成这一操作呢?下面为您阐述. 思路是这样的: 1.在ListV ...

  10. 使用awstats分析iis站点的日志

    环境:win7 + iis7 + perl(ActivePerl-5.20.1.2000) + awstats 7.3 一.找到iis日志所在目录 建议全部都打勾 二.安装perl AWStats是p ...