selectのソケット数の制限

3367 ワード

selectモデルの場合、ローテーションされたソケットの数はマクロFD_を受け取るSETSIZEの制限(linuxのデフォルトは1024、windowsは64).この制限を回避するには、テクニックを使用します(selectモデルのホイールトレーニング特性のため、ホイールトレーニングソケットの数を大きく設定することは推奨されません).
1、配列の長さの拡張C言語の1つの技巧は構造体の中の最後のメンバーの配列の長さを拡張して、コードは以下の通りです:
typedef struct _str_type
{
    int _len;
    char _s[1];
}str_type;
 
int str_len = 100;//  _s   100  
str_type *s = (str_type*) malloc( sizeof( str_type ) + str_len - 1 );
free( s ); 

要件:
1)動的成長が必要なメンバーは、構造体の末尾にある必要があります._sは構造体の尾部にぴったりあるので,連続した空間を割り当てることができる.
2)str_typeで定義された変数は、十分な長さのスタックまたはスタックメモリに割り当てる必要があります.
3)構造体内にc++のものを含んではいけない.そうしないと安全ではない.実際には虚表は含まれないはずです.(参考)
2、selectの応用例
(1)fd_set構造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; 

(2)カスタムマクロは,カスタムマクロを用いて配列を加える必要がある.
cライブラリバージョンの追加記述子は配列のマクロに以下のようになるため、ライブラリを含むマクロFD_SETSIZE
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) 

配列のマクロに記述子を追加する独自のバージョンを書く
#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 ) 

(3)配列unsigned int count=2000に記述子を加える.
//自分で指定した2000個のソケットの制限に変更しました(個数は自定可能)
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 ); 
(4)selectインスタンスコード1)ポーリングread
int r = select( 0, &read_set, 0, 0, &timeout );
if( r < 0 )
{
    // select error
} 
else if( r > 0 )
{
    for( each sockets )
    {
        if( FD_ISSET( now_socket, &read_set ) ) 
        {
            // this socket can read data
        }
    }
} 

2)ポーリングwriteとread
// read_set, write_set          fd_set     
int r = select( 0, read_set, write_set, 0, &timeout );
if( r < 0 )
{
    // select error
}  
for( int i = 0; i < read_set->fd_count; ++ i )
{
    //   socket(   FD_ISSET)
    if(read_set->fd_array[i] == now_socket)
    {
    //do reading 
    }
} 


for( int i = 0; i < write_set->fd_count; ++ i )
{
    //   socket
    if(write_set->fd_array[i] == now_socket)
    {
    //do writing 
    }
}