青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

突破select的FD_SETSIZE限制

Author : Kevin Lynx 

前言:

在很多比較各種網(wǎng)絡(luò)模型的文章中,但凡提到select模型時(shí),都會(huì)說(shuō)select受限于輪詢的套接字?jǐn)?shù)量,這個(gè)
數(shù)量也就是系統(tǒng)頭文件中定義的FD_SETSIZE值(例如64)。但事實(shí)上這個(gè)算不上真的限制。

C語(yǔ)言的偏方:

在C語(yǔ)言的世界里存在一個(gè)關(guān)于結(jié)構(gòu)體的偏門技巧,例如:

 

typedef struct _str_type
{
   
int _len;
   
char _s[1];
}
str_type;

 

str_type用于保存字符串(我只是舉例,事實(shí)上這個(gè)結(jié)構(gòu)體沒(méi)什么用處),乍看上去str_type只能保存長(zhǎng)度為
1的字符串('\0')。但是,通過(guò)寫(xiě)下如下的代碼,你將突破這個(gè)限制:

int str_len = 5;
str_type
*s = (str_type*) malloc( sizeof( str_type ) + str_len - 1 );
//
free( s );


這個(gè)技巧原理很簡(jiǎn)單,因?yàn)開(kāi)s恰好在結(jié)構(gòu)體尾部,所以可以為其分配一段連續(xù)的空間,只要注意指針的使用,
這個(gè)就算不上代碼上的罪惡。但是這個(gè)技巧有個(gè)限制,str_type定義的變量必須是被分配在堆上,否則會(huì)破
壞堆棧。另外,需要?jiǎng)討B(tài)增長(zhǎng)的成員需要位于結(jié)構(gòu)體的末尾。最后,一個(gè)忠告就是,這個(gè)是C語(yǔ)言里的技巧,
如果你的結(jié)構(gòu)體包含了C++的東西,這個(gè)技巧將不再安全(<Inside the C++ object model>)。

其實(shí)select也可以這樣做:

事實(shí)上,因?yàn)閟elect涉及到的fd_set是一個(gè)完全滿足上述要求的結(jié)構(gòu)體:

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;


但是,如果使用了以上技巧來(lái)增加fd_array的數(shù)量(也就是保存的套接字?jǐn)?shù)量),那么關(guān)于fd_set的那些宏可
能就無(wú)法使用了,例如FD_SET。

winsock2.h :

#define FD_SET(fd, set) do { \
    u_int __i; \
   
for (__i = 0; __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(0)


有點(diǎn)讓人眼花繚亂,我鼓勵(lì)你仔細(xì)看,其實(shí)很簡(jiǎn)單。這里有個(gè)小技巧,就是他把這些代碼放到一個(gè)do...while(0)
里,為什么要這樣做,我覺(jué)得應(yīng)該是防止名字污染,也就是防止那個(gè)__i變量與你的代碼相沖突??梢钥闯觯?br>FD_SET會(huì)將fd_count與FD_SETSIZE相比較,這里主要是防止往fd_array的非法位置寫(xiě)數(shù)據(jù)。

因?yàn)檫@個(gè)宏原理不過(guò)如此,所以我們完全可以自己寫(xiě)一個(gè)新的版本。例如:

#define MY_FD_SET( fd, set, size ) do { \
    unsigned
int i = 0; \
   
for( i = 0; 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( 0 )


沒(méi)什么變化,只是為FD_SET加入一個(gè)fd_array的長(zhǎng)度參數(shù),宏體也只是將FD_SETSIZE換成這個(gè)長(zhǎng)度參數(shù)。
于是,現(xiàn)在你可以寫(xiě)下這樣的代碼:

unsigned int count = 100;
fd_set
*read_set = (fd_set*) malloc( sizeof( fd_set ) + sizeof(SOCKET) * (count - FD_SETSIZE ) );
SOCKET s
= socket( AF_INET, SOCK_STREAM, 0 );
//
MY_FD_SET( s, read_set, count );
//
free( read_set );
closesocket( s );


小提下select模型:

這里我不會(huì)具體講select模型,我只稍微提一下。一個(gè)典型的select輪詢模型為:

int r = select( 0, &read_set, 0, 0, &timeout );
if( r < 0 )
{
   
// select error
}
 

if( r > 0 )
{
   
for( each sockets )
   
{
       
if( FD_ISSET( now_socket, &read_set ) )
       
{
           
// this socket can read data
        }

    }

}
 


輪詢write時(shí)也差不多。在Etwork(一個(gè)超小型的基本用于練習(xí)網(wǎng)絡(luò)編程的網(wǎng)絡(luò)庫(kù),google yourself)中,作者
的輪詢方式則有所不同:

// read_set, write_set為采用了上文所述技巧的fd_set類型的指針
int r = select( 0, read_set, write_set, 0, &timeout );
//  error handling
for( int i = 0; i < read_set->fd_count; ++ i )
{
   
// 輪詢所有socket,這里直接采用read_set->fd_array[i] == now_socket判斷,而不是FD_ISSET
}
 

for( int i = 0; i < write_set->fd_count; ++ i )
{
   
// 輪詢所有socket,檢查其whether can write,判斷方式同上
}
 


兩種方式的效率從代碼上看去似乎都差不多,關(guān)鍵在于,F(xiàn)D_ISSET干了什么?這個(gè)宏實(shí)際上使用了__WSAFDIsSet
函數(shù),而__WSAFDIsSet做了什么則不知道。也許它會(huì)依賴于FD_SETSIZE宏,那么這在我們這里將是不安全的,
所以相比之下,如果我們使用了這個(gè)突破FD_SETSIZE的偏方手段,那么也許第二種方式要好些。

相關(guān)下載(5.21.2008)

隨便寫(xiě)了一個(gè)改進(jìn)的select模型的echo服務(wù)器,放上源碼

posted on 2008-05-20 11:20 Kevin Lynx 閱讀(22449) 評(píng)論(12)  編輯 收藏 引用 所屬分類: game developnetwork

評(píng)論

# re: 突破select的FD_SETSIZE限制 2008-05-20 11:49 2nd guest

何必搞那么復(fù)雜,叫人怎么維護(hù)呢?  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-05-20 13:03 Kevin Lynx

@2nd guest
我覺(jué)得這個(gè)東西不復(fù)雜,只要保持模塊對(duì)外接口的簡(jiǎn)潔,維護(hù)這么小的模塊不會(huì)那么復(fù)雜。  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-05-20 13:16 eXile

可以參考 boost::asio中的detail/win_fd_set, 很簡(jiǎn)單  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-05-20 14:24 Kevin Lynx

@eXile
謝謝提醒,win_fd_set_adapter.hpp確實(shí)是個(gè)方案。那估計(jì)是用__WSAFDIsSet也不是問(wèn)題了。:)   回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-05-20 16:44 hsen

__WSAFDIsSet 好像是Windows的API吧。Windows下的select有這個(gè)限制嗎?  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制[未登錄](méi) 2008-05-24 20:40 christanxw

多此一舉。直接重新FD_SETSIZE不就是了,何必搞這么復(fù)雜。  回復(fù)  更多評(píng)論   

# 突破select的FD_SETSIZE限制[未登錄](méi) 2008-05-24 20:41 christanxw

多此一舉。直接重新定義FD_SETSIZE不就是了,何必搞這么復(fù)雜。  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-07-03 01:47 denny

@christanxw

正因?yàn)镕D_SETSIZE是系統(tǒng)宏,所有才有這個(gè)問(wèn)題,要不你重新編譯內(nèi)核,那么這種解決方案也不具有通用性  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2008-10-29 11:42 itssunny

其實(shí)沒(méi)必要這么費(fèi)勁,只要在包含 winsock2.h 頭文件的前面重新define 一下 FD_SETSIZE 的值就可以修改這個(gè)限制。但為了性能考慮這樣做沒(méi)什么太大意義,最好還是用重疊io或完成端口等異步模型性能好。  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制[未登錄](méi) 2010-05-14 23:58 ttylikl

do{}while(0)的解釋錯(cuò)誤呢
考慮這種情況:
if(****)
FD_SET(....);
else
FD_SET(....);

這個(gè)時(shí)候do {} while(0)就很重要啦。  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2011-01-21 11:10 jmzz

直接重新定義FD_SETSIZE即可

ws2_32.dll中_WSAFDIsSet的實(shí)現(xiàn)

int __stdcall _WSAFDIsSet(SOCKET fd, fd_set *a2)
{
int result; // eax@1
u_int v3; // ecx@1
char *v4; // edx@2

v3 = a2->fd_count;
result = 0;
if ( a2->fd_count )
{
v4 = (char *)&a2->fd_array[v3];
do
{
v4 -= 4;
if ( *(_DWORD *)v4 == fd )
result = 1;
--v3;
}
while ( v3 );
}
return result;
}
  回復(fù)  更多評(píng)論   

# re: 突破select的FD_SETSIZE限制 2013-08-31 15:30 lkz

MSDN說(shuō)了,在include頭文件前重新定義FD_SETSIZE即可……  回復(fù)  更多評(píng)論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            狠狠色综合色区| 久久漫画官网| 亚洲国产精品一区二区第四页av | 亚洲欧美日韩直播| 亚洲国产精品va在线观看黑人 | 亚洲国产另类久久精品| 国产乱码精品一区二区三区忘忧草| 欧美成人嫩草网站| 久久精品国产亚洲a| 亚洲性图久久| 一区二区久久久久久| 亚洲高清在线播放| 美女视频黄免费的久久| 欧美在线不卡视频| 午夜精品久久久久| 亚洲一区二区视频在线| 99精品视频网| 亚洲美洲欧洲综合国产一区| 亚洲国产另类精品专区 | 中文久久精品| 亚洲精品偷拍| 亚洲精品黄色| 亚洲激情在线| 亚洲欧洲视频| 91久久黄色| 亚洲人成高清| 亚洲精品一二| 亚洲免费精品| 宅男66日本亚洲欧美视频| 亚洲人成人一区二区在线观看| 影院欧美亚洲| 最新日韩精品| 亚洲精品无人区| aa级大片欧美三级| 一区二区久久久久| 在线视频精品| 亚洲欧美中文另类| 久久国产精品久久久久久电车| 欧美一区二区三区久久精品| 欧美一级夜夜爽| 欧美在线播放一区| 久久亚洲国产精品一区二区 | 欧美激情视频网站| 欧美日韩三级一区二区| 欧美日韩视频专区在线播放| 国产精品videossex久久发布| 国产精品高潮在线| 国产欧美日韩不卡免费| 狠狠综合久久av一区二区老牛| 在线观看成人小视频| 最新中文字幕亚洲| 一区二区三区欧美日韩| 午夜精品视频在线| 久久蜜臀精品av| 亚洲电影下载| 99国产精品| 欧美一区二区日韩一区二区| 久久免费视频在线| 欧美精品一区在线发布| 国产精品视频yy9099| 激情欧美国产欧美| 亚洲美女一区| 久久国产精品72免费观看| 免费亚洲网站| 一本大道久久a久久综合婷婷| 午夜久久影院| 免费一级欧美片在线播放| 国产精品vvv| 伊人色综合久久天天| 一本色道久久综合亚洲精品小说| 午夜精品免费在线| 欧美激情国产高清| 日韩亚洲视频| 久久精品中文字幕一区| 欧美日本在线观看| 国内精品模特av私拍在线观看| 亚洲黄色三级| 久久av最新网址| 亚洲欧洲一区二区天堂久久| 香蕉久久精品日日躁夜夜躁| 欧美国产欧美亚州国产日韩mv天天看完整| 国产精品久久久久9999| 亚洲成人影音| 午夜欧美大尺度福利影院在线看| 美女黄毛**国产精品啪啪| 99一区二区| 老牛嫩草一区二区三区日本| 国产精品免费观看视频| 91久久精品国产91性色| 久久动漫亚洲| 一二三区精品| 嫩草国产精品入口| 国产日韩综合一区二区性色av| 一区二区欧美在线| 母乳一区在线观看| 亚洲午夜国产一区99re久久| 欧美v亚洲v综合ⅴ国产v| 国产丝袜一区二区三区| 在线一区二区三区四区| 欧美成人午夜77777| 欧美亚洲免费在线| 国产精品成人观看视频免费| 亚洲乱码国产乱码精品精98午夜 | 欧美成人精品不卡视频在线观看| 国产麻豆日韩| 亚洲一区在线播放| 亚洲欧洲偷拍精品| 蜜臀av国产精品久久久久| 国产精品一区二区在线观看网站 | 国产午夜精品麻豆| 亚洲在线1234| 日韩视频―中文字幕| 欧美不卡高清| 亚洲国产第一页| 美女黄色成人网| 久久久久久夜| 激情小说亚洲一区| 久久久夜夜夜| 久久国产福利国产秒拍| 国产日韩欧美a| 欧美在线免费观看视频| 亚洲无毛电影| 国产精品嫩草影院av蜜臀| 亚洲在线免费观看| 亚洲无限av看| 国产精品自拍视频| 午夜精品福利在线观看| 亚洲一区二区三区乱码aⅴ| 国产精品xnxxcom| 午夜精品久久久久久久99水蜜桃| 亚洲一区二区三区高清不卡| 国产精品美女久久久久久2018| 亚洲在线播放| 亚洲欧美日韩成人高清在线一区| 国产精品久线观看视频| 性欧美18~19sex高清播放| 亚洲在线视频一区| 国产深夜精品福利| 久久综合伊人77777蜜臀| 久久久国产一区二区| 亚洲国产美女久久久久| 亚洲国产另类久久精品| 欧美日本韩国| 亚洲欧美成aⅴ人在线观看| 亚洲欧美欧美一区二区三区| 国模一区二区三区| 欧美超级免费视 在线| 欧美激情日韩| 亚洲欧美影音先锋| 欧美一区二区日韩| 亚洲国产精品va在看黑人| 亚洲国产美国国产综合一区二区 | 国产一区二区三区的电影| 久久久久九九九| 鲁大师影院一区二区三区| 亚洲精品老司机| 夜夜爽夜夜爽精品视频| 国产精品一卡| 欧美刺激性大交免费视频| 欧美日韩喷水| 久久久久久久激情视频| 欧美大胆成人| 亚洲综合丁香| 久久久视频精品| 一本色道久久综合亚洲二区三区| 亚洲在线成人精品| 亚洲二区在线视频| 一区二区欧美视频| 一区在线免费| 一区二区福利| 怡红院av一区二区三区| 99精品视频免费在线观看| 狠狠色综合播放一区二区| 亚洲精品看片| 激情成人在线视频| 一本色道久久综合亚洲91| 狠狠色综合播放一区二区| 日韩午夜三级在线| 精品动漫3d一区二区三区免费 | 国户精品久久久久久久久久久不卡| 欧美好吊妞视频| 国产视频亚洲精品| 亚洲六月丁香色婷婷综合久久| 国内伊人久久久久久网站视频| 亚洲精品视频中文字幕| 国产一区二区三区不卡在线观看| 亚洲精品视频一区二区三区| 国产综合欧美| 一区二区三区欧美激情| 在线观看日韩精品| 亚洲一区二区三区高清不卡| 亚洲日本理论电影| 欧美亚洲一区二区三区| 一区二区三区久久网| 久久免费视频在线观看| 久久高清福利视频| 欧美性大战久久久久久久| 亚洲国产精品久久91精品| 国产婷婷精品| 亚洲色在线视频|