2009-09-02 36 views
0

WindowsソケットでWSAEventSelect I/Oモデルを使用しています。これで、送受信操作によってすべてのデータが送受信されたことをどのように知ることができますか?Winsock送受信します。

私が知った後、データを完全に送信する方法をどのように設計する必要がありますか?どの例も本当に感謝しています。私は受け取るが(メッセージをします完了したと判断するブール値のフラグを設定するだろうと、思った何

SOCKET SocketArray [WSA_MAXIMUM_WAIT_EVENTS]; 
WSAEVENT EventArray [WSA_MAXIMUM_WAIT_EVENTS], 
NewEvent; 
SOCKADDR_IN InternetAddr; 
SOCKET Accept, Listen; 
DWORD EventTotal = 0; 
DWORD Index, i; 
WSANETWORKEVENTS NetworkEvents; 


// Set up socket for listening etc... 
// .... 

NewEvent = WSACreateEvent(); 

WSAEventSelect(Listen, NewEvent, 
       FD_ACCEPT │ FD_CLOSE); 

listen(Listen, 5); 

SocketArray[EventTotal] = Listen; 
EventArray[EventTotal] = NewEvent; 
EventTotal++; 

while(TRUE) 
{ 
    // Wait for network events on all sockets 
    Index = WSAWaitForMultipleEvents(EventTotal, 
     EventArray, FALSE, WSA_INFINITE, FALSE); 
    Index = Index - WSA_WAIT_EVENT_0; 

    // Iterate through all events to see if more than one is signaled 
    for(i=Index; i < EventTotal ;i++ 
    { 
     Index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000, 
      FALSE); 
     if ((Index == WSA_WAIT_FAILED) ││ (Index == WSA_WAIT_TIMEOUT)) 
      continue; 
     else 
     { 
      Index = i; 
      WSAEnumNetworkEvents(
       SocketArray[Index], 
       EventArray[Index], 
       &NetworkEvents); 

      // Check for FD_ACCEPT messages  
      if (NetworkEvents.lNetworkEvents & FD_ACCEPT) 
      { 
       if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) 
       { 
        printf("FD_ACCEPT failed with error %d\n", 
         NetworkEvents.iErrorCode[FD_ACCEPT_BIT]); 
        break; 
       } 

       // Accept a new connection, and add it to the 
       // socket and event lists 
       Accept = accept(
        SocketArray[Index], 
        NULL, NULL); 

       NewEvent = WSACreateEvent(); 

       WSAEventSelect(Accept, NewEvent, 
        FD_READ │ FD_CLOSE); 

       EventArray[EventTotal] = NewEvent; 
       SocketArray[EventTotal] = Accept; 
       EventTotal++; 
       printf("Socket %d connected\n", Accept); 
      } 

      // Process FD_READ notification 
      if (NetworkEvents.lNetworkEvents & FD_READ) 
      { 
       if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0) 
       { 
        printf("FD_READ failed with error %d\n", 
         NetworkEvents.iErrorCode[FD_READ_BIT]); 
        break; 
       } 

       // Read data from the socket 
       recv(SocketArray[Index - WSA_WAIT_EVENT_0], 
        buffer, sizeof(buffer), 0); 

       // here I do some processing on the data received 
       DoSomething(buffer); 

       // now I want to send data 
       send(SocketArray[Index - WSA_WAIT_EVENT_0], 
         buffer, sizeof(buffer), 0); 
       // how can I be assured that the data is sent completely 

      } 

      // FD_CLOSE handling here 
      // ...... 
      // ...... 
     } 
    } 
} 

:ここ

コード(私はから学んでいる本からのサンプルコード)であります長さの接頭辞を付けて)、そのデータの処理を開始します。しかし、はどうですか??可能性を教えてください。

** EDIT:**場合は、処理しているプロトコル(アプリケーション層)は、あなたが受け取るしようとしているどのように多くのデータに関する情報を提供しない限り、FD_READイベント一部

答えて

0

を参照してください決定する唯一の方法ピアが切断するときに受信するものはもうありません。サーバーが単に送信を停止した場合、サーバーはその終了か単にビジーであるかどうか判断できません。終了時に終了します。また、サーバーが終了したために接続が切断されたのか、接続が切断されたのかを判断することもできません。

ほとんどのプロトコルは、それを送信する前に送信される予定のバイト数、またはデータの最後に境界線を置くことによって、ピアに通知します。

送信については、使用しているバッファに注意する必要があります。 send()にすると、バッファに移動します(デフォルトでは64KB)。 send()はバッファに格納されたバイト数を返します。送信しようとしていたバイト数よりも小さい場合、FD_WRITEイベントを受け取ったときに再試行する必要があります。

通知がない限り、ピアによってすでに受信されたデータの量を確認することはできません(mIRC DDCはこれを行います)。

は、それがあなたの疑問をclearfyedわからない、あなたがデータを受信したかどうかを判断するために、リターン・ステータスを保存する必要があり、あなたはRECVをしているとき、それは

+0

問題は、FD_WRITEイベントを待っているわけではありません。なぜなら、内部バッファがいっぱいになり、FD_WRITEイベントを再び送信するのに十分なデータを送信する必要があるからです。私がやっていることは、非同期で送信することですが、データが正常に送信されたことを知る必要があります。それ、どうやったら出来るの? – akif

+0

私は短いメッセージ(1,2バイト)を送信しているので、単純に、あなたはFD_WRITE :) – Havenard

+0

を待っています。内部バッファがいっぱいでない限り、別のFD_WRITEイベントを取得しません。 – akif

0

:)を助け願っています。 recvは受け取ったバイト数を返し、4番目のパラメータにはすべてのメッセージを受け取るために、バッファサイズに基づいてゼロの代わりにフラグMSG_WAITALLを使用します。ステータスrecvの戻り値が負の場合は、接続が相手側から近づいているなど、何らかの問題がありました。

sendに関しては、戻り値もステータスとして保存する必要がありますが、この場合、返す前にすべてのデータを送信するフラグはありません。送信量とバッファーを調整し、値に基づいてサイズを送信する必要があります。 recvと同様に、負の値はエラーが発生したことを示します。

戻り値とフラグの詳細については、recvsendのMicrosoft Webサイトの関数の説明を参照してください。

+0

MSG_WAITALLはSOCK_DGRAM(UDPおよびRAW)用です。 SOCK_STREAM(TCP)がハングします。 – Havenard

関連する問題