Winsockのネットワークプログラミング・ノート:EventSelectモデル

WSAEventSelectモデルとモデルの違いWSAAsyncSelect

同じポイント:

1.ネットワークイベントは、システム通知アプリケーションによって処理される
2非同期で
相違:通知メカニズムは同じではない、WSAAsyncSelectモデルは、アプリケーションに通知するために、Windowsメッセージ機構に基づいています。WSAEventSelectモデルは、イベント通知の形です。したがって、必要性の窓、1はしていません。

プロセスのモデル

 

 

 

 

 

 

 

詳細な相関関数

WSACreateEvent

 機能のWSACreateEventの戻り値は、それらがネットワークの種類に興味があるイベントを登録している間、それは一緒にソケットに関連付けられている必要があり、優れたイベントオブジェクトのハンドルを作成するだけです

1  INT WSAEventSelect( 
 2  
。3          SOCKET S、                        // 関心ソケットの代表
4  
。5          WSAEVENT hEventObject、          // 指定されたイベントオブジェクトは、一緒にソケットに関連すること、すなわち、とWSACreateEvent作成した
。6  
。7          ロング lNetworkEvents             / / 関心指定されたアプリケーションのネットワークイベントの様々な種類の組み合わせは、「ビットマスク」に対応する。
8。 
9。      )。

パラメータは以下の値とOR演算であってもよい、請求LNetworkEvents。

       FD_READアプリケーションは、データが読みそうすることを、読みやすいかどうかについての通知を受けたいです

       FD_WRITEアプリケーションがデータを書き込むかどうか、書き込みへの通知を受けたいです

       FD_ACCEPTアプリケーションが入ってくるとの接続に関する通知を受信したいです

       FD_CONNECTアプリケーションは、接続完了の通知を受けたいです

       FD_CLOSEアプリケーションは、ソケットの閉鎖の通知を受けたいです

 

WSAWaitForMultipleEvents

WSAAPI WSAWaitForMultipleEvents DWORD(
  DWORD cEvents、                 // イベントの数待ち
  のconst WSAEVENT FAR * lphEvents、// イベントオブジェクトの配列 
  BOOL fWaitAll、                 // イベントがソケットのすべて戻るまで待つかどうか 
  、DWORD dwTimeoutを               // ミリ秒で、待ち時間を、 WSA_INFINEは無期限に待機表さ 
  BOOL fAlertable                // FALSEに最初のセットを 
)。

 

 

    cEventslphEvents WSAEVENTオブジェクトからなる配列を定義するパラメータ。この配列では、cEventsはのために、対応するlphEventsにイベントオブジェクトの数、およびポインタを指定します

アレイへの直接参照。本明細書で定義されるWSAWaitForMultipleEventsとしてのみWSA_MAXIMUM_WAIT_EVENTSオブジェクト64によって定義された最大値をサポートすることができることに留意されたいです。そのため、用

WSAWaitForMultipleEventsは、各スレッドの呼び出しを発行し、I / Oモデルは、64個のソケットの最大をサポートすることができます。あなたはこのモデルはまた、64個の以上のソケットを管理したい場合は、余分な作業を作成する必要があります

スレッドによって、順番に複数のイベントオブジェクトを待機します。

     fWaitAllパラメータを指定する方法オブジェクトのWSAWaitForMultipleEventsは、イベントの配列を待ちます。TRUEに設定すると、すべてのオブジェクトと一つだけ、このようなイベントは、配列lphEventsは「持っているに入っている付属しました

「状態を関数が返す;しかしに任意のイベントオブジェクト、FALSEに設定されている場合、」シグナル文字が「ステータスを渡された、機能が後者に戻り、戻り値は、最終的にイベントオブジェクトを表すことれています。結果の関数

リターン。通常、アプリケーションは一度のみソケットイベントを提供し、このパラメータをFALSEに設定する必要があります。

    dwTimeoutのパラメータはミリ秒単位で、これは設定「タイムアウト」でどのくらいの時間、発生したネットワークイベントを待つWSAWaitForMultipleEventsを指定します。割り当てられた時間を超えて、機能

また、満たされていないfWaitAllパラメータで指定された条件は、そうしても、すぐに返します。考慮による性能への影響を考えると、タイムアウト値が0に設定されているのは避けるべきです。処理待ちのイベントがない場合は、

WSAWaitForMultipleEventsはWSA_WAIT_TIMEOUTを返します。dwTimeoutは、イベントオブジェクトをシグナル伝達ネットワークの場合には、その後、(永久に待機)WSAINFINITEを設定するように

関数の後には戻りません。

   fAlertableパラメータ、我々は無視できる、とFALSEに設定する必要がありWSAEventSelectモデルを、使用しています。これは主に、オーバーレイI / Oモデルで使用され、処理ルーチンがで完了します

使用。

    この関数は、インデックスを返すいくつかのネットワークイベントオブジェクトの最初を示し、この指数によれば、次のコールWSAEnumNetworkEventsイベントがソケット上で発生したかを決定するために、ソケットへのインデックスであってもよいです。その結果、我々のアプリケーションは、イベントの配列を参照することができます

文字がソケットに対応するイベントと取り出しが、ソケットの端部で判定され、イベントに渡された、ネットワークイベントの種類が発生しました。イベントのイベント参照配列は、使用されるべきである場合

WSAWaitForMultipleEvents(すなわち、インデックス位置)は、特定の基準値を与えるために、予め定義された値WSA_WAIT_EVENT_0を減算し、値を返します

 

WSAEnumNetworkEvents

1  int型 WSAEnumNetworkEvents(     // 正常終了0 
2    SOCKET S、                
 3。    WSAEVENT hEventObject、      // ソケットネットワークイベントオブジェクト
4。    LPWSANETWORKEVENTSのlpNetworkEvents // ネットワーク構造ポインタ
5)。

 

    ソケット・ネットワーク・イベントの結果に応じたパラメータs。

    hEventObjectパラメータはオプションです。それは、リセットしようとするイベントオブジェクトに対応するイベントハンドラを指定します。そう、それが自動的に、渡すことができるように、我々のイベントオブジェクト、状態を「手紙が渡されました」ので、

状態を「シグナルではない」になるために。あなたはパラメータhEventObjectイベントをリセットしたくない場合は、WSAResetEvent機能を使用することができ、それが機能する前に議論されてきました。

    受信ソケットと発生する可能性のあるエラーコードで発生するネットワークイベント・タイプのポインタWSANETWORKEVENTS構造を表すパラメータlpNetworkEvents。

 

 

ケースコード

#include <入出力ストリーム> 
の#include " ../common/initsock.h " 
使用 名前空間STD; 

CInitSock initSock; 


int型のmain()
{ 
    WSAEVENT eventArray [WSA_MAXIMUM_WAIT_EVENTS]; // イベントアレイ作成 
    SOCKET socketArray [WSA_MAXIMUM_WAIT_EVENTSを]; // スリーブを作成しますグループアクセスワード
    int型 EventSum = 0 ; 
    
    USHORTポート = 4567 ; 
    SOCKET聞く = ::ソケット(AF_INET、SOCK_STREAM、IPPROTO_TCPのゴー); 
    のsockaddr_inアドレス; 
    address.sin_family = AF_INET; 
    address.sin_port =htons(ポート); 
    address.sin_addr.S_un.S_addr = INADDR_ANY。

    もし(::バインド(聞く、(のsockaddr *)&アドレス、はsizeof(アドレス))== SOCKET_ERROR)// 绑定
    { 
        裁判所未満 << " 绑定套接字失败!" << てendl;
        リターン - 1 
    } 

    ::(、聞く耳を傾け5 )。

    WSAEVENTのイベント = WSACreateEvent()。
    :: WSAEventSelect(聞く、イベント、FD_ACCEPT | FD_CLOSE)。
    eventArray [EventSum] = イベント
    socketArray [EventSum] = 聞きます。
    EventSum ++ ; 

    一方、
    { 
        int型のインデックス= WSAWaitForMultipleEvents(EventSum、eventArray、、WSA_INFINITE、)。
        以下のためにINT iがインデックスを=; I <EventSum; I ++ 
        { 
            インデックス = :: WSAWaitForMultipleEvents(1、&​​eventArray [i]は、TRUE、1000年、FALSE)。
            もし(インデックス== WSA_WAIT_FAILED ||インデックス== WSA_WAIT_TIMEOUT)
            { 
                続けます
            } 
            
            { 
                WSANETWORKEVENTSのイベント
                :: WSAEnumNetworkEvents(socketArray [I]、eventArray [i]は、イベント)。
                もしイベント .lNetworkEvents&FD_ACCEPT)
                { 
                    場合イベント .iErrorCode [FD_ACCEPT_BIT] == 0 
                    { 
                        場合(EventSum> WSA_MAXIMUM_WAIT_EVENTS)
                        { 
                            COUT << " 连接过多!" <<endl;
                            続け; 
                        } 
                        SOCKET NewSocket = ::(socketArray [i]は、NULL、NULL)を受け入れます。
                        WSAEVENTのイベント = :: WSACreateEvent(); 
                        :: WSAEventSelect(NewSocket、イベント、FD_READ | FD_CLOSE | FD_WRITE); 
                        eventArray [EventSum] = イベント
                        socketArray [EventSum] = NewSocket。
                        EventSum ++ ; 

                    } 
                } 
            
             もしイベント .lNetworkEvents&FD_READ)
            { 
                    [リモートのsockaddr_in。
                もしイベント .iErrorCode [FD_READ_BIT] == 0 
                { 
                    チャーメッセージ[ 1000年]。
                    INT IND = :: RECV(socketArray [i]は、メッセージ、strlenを(メッセージ)、0 );
                    もし(IND> 0 
                    { 
                        メッセージ[IND] = ' \ 0 ' 
                        
                        printf("服务器收到数据:%S \ n " 、メッセージ); 
                    } 
                } 
            } 
            そう であればイベント .lNetworkEvents&FD_CLOSE)
            { 
                場合イベント .iErrorCode [FD_CLOSE_BIT] == 0 
                { 
                    :: closesocket(socketArray [I])。
                    INT ; J <EventSum - J = 1 ; J ++ 
                    { 
                        socketArray [J] = socketArray [J + 1 ]; 
                        eventArray [J]= eventArray [J + 1 ]。
                    } 
                    EventSum - 
                } 
            } 

            } 
        } 
    } 

    
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/Romantic-Chopin/p/12457927.html