2011-10-31 5 views
1

静的なクラスでデータを正常に送信することができます。ソケットプログラミングでは、データの量は少なくて済みますが、実稼働環境ではいつかフリーズしてデータを送信し始めています。問題ですか?助けてもらえますか?コードは以下の通りです。いつかデータがフリーズし、いつかは遅れるようにするためのソケットプログラミング

  DWORD BytesCount; 
    WSABUF Buffer[1]; 
    DWORD Flag = 0; 

    Buffer[0].len = SendLength; 
    Buffer[0].buf = SendData; 
    if (WSASend(*socket, Buffer, 1, &BytesCount, Flag, NULL, NULL) != SOCKET_ERROR) 
    { 
     if (BytesCount != SendLength) 
      Result = -2; 
     else 
     { 
      if (ReturnAnswer) 
      { 
       int Res = 0, recBufStart; 
       DWORD RecvCount = 0, AllRecv = 0; 

       Buffer[0].len = ReceiveLength; 
       Buffer[0].buf = ReceiveData; 
       recBufStart = 0; 
       saAction = saReceive; 

       // We need to Receive until we get all the data. When WSARecv call might only return zero bytes 
       bool Stop = true; // true as we dont need to recieve anything from the server. 
       while (!Stop) 
       { 
        Res = WSARecv(*socket, &Buffer[recBufStart], (recBufStart == 0 ? 1 : 0), &RecvCount, &Flag, NULL, NULL); 
        if (Res == SOCKET_ERROR) 
         Stop = true; 
        else 
        { 
         AllRecv = AllRecv + RecvCount; 
         if (AllRecv == ReceiveLength || RecvCount == 0) 
          Stop = true; // Stop 
         else 
         { 
          Buffer[0].buf = &ReceiveData[AllRecv]; 
          Buffer[0].len = ReceiveLength - (AllRecv); 
          recBufStart = 0; 
         } 
        } 
       } 

       if (Res == SOCKET_ERROR) 
        Result = WSAGetLastError();     
      } 
     } 
    } 
    else 
     Result = WSAGetLastError();  
+0

WSASendまたはWSARecvでフリーズしていますか? –

+0

私はWSASendを使用しています。ブール値がtrueに設定されていることがわかるように、私は何も受信していません。 – Ershad

答えて

1

私は、これが問題になるかどうかはわからないが、のWSASendのためのMicrosoftのドキュメントから、次があります:

なlpOverlappedパラメータセットとのWSASendとしてブロッキングWinsockの呼び出しを発行しますNULLにすると、Winsockは呼び出しが完了する前にネットワークイベントを待機する必要があります。

また、受信コードはかなり複雑に思えます。どの場合、recBufStartは0以外のものになるでしょうか?私は変数 "Stop"も使用しません。 break文を発行してwhileループを終了するだけです。

EDIT:あなたの受信コードを少し詳しく見て、while(!Stop)の前にStopをtrueに設定します。つまりwhile(Stop == false)です。だからWSARecvには行きません。これは意図的ですか?そうであれば、マイクロソフトの説明と私の回答はあなたの問題を示しているようです。つまり、継続して送信していて、Winsockはより多くのデータを送信できるように待つ必要があります。

+0

OK、意図的に私は現在何のデータも受信していませんし、あなたが言っていることが正しいと思われる問題があるので、これを避けるために何をしなければなりませんか?私はソケットを作成し、タイムアウトエラーの間に取得中に選択を使用しています。 – Ershad

+0

私は実際にデータを送信し、受信しないコードは見たことがありません。私はあなたが送っているピアから何かを返す必要があると思うでしょう。その時点で、WSASendのブロックを解除するネットワークイベントが発生するでしょう。テストするだけでWSASendを実行してからWSARecvを実行するだけです。 MicrosoftインターフェイスよりもBerkeleyソケットインターフェイスを使用する方が、この重複したI/Oのすべてを避けることができます。つまり、WSASec、ソケットではなく、WSARecvではなくWSASocketとrecvを送信します。 – rushman

0

WSASendを使用していて、WSARecvがブロックモードです(最後の2つのパラメータはNULLです)。これは、TCP/IPスタックバッファをいっぱいにするとすぐに、WSASendへの次の呼び出しは、バッファにもう一度スペースがある(つまり、データが送信される)までブロックされることを意味します。

さらに、非同期呼び出しとI/O completion portsを使用することをお勧めします。

+0

私はこれを使用してタイムアウトになっていますが、これが問題の原因です。コードは以下の通りです。もし(選択(0、NULL、&ConnectSockets、NULL、&タイムアウト)== SOCKET_ERROR) \t { \t \t LogToEventLog(EVENTLOG_WARNING_TYPE、EVENTID_WINSOCK_ERROR、_T( "プライマリサーバー接続が失敗しました - エラー%ldので選択コール")を、WSAGetLastError( )); \t \t閉じる(SocketPrimary、TRUE); \t \t falseを返します。 \t {\t \t他 \t} \t IF(ConnectSockets.fd_count == 0) \t \t { \t \t \t LogToEventLog(EVENTLOG_WARNING_TYPE、EVENTID_WINSOCK_ERROR、_T( "プライマリサーバ接続失敗 - TIMEDOUTが接続..." )); \t \t \t閉じる(SocketPrimary、TRUE); \t \t \t falseを返します。 \t \t} \t} – Ershad

0

アプリケーションがソケットの送信バッファサイズより大きいデータブロックを送信すると、TCPスタックがアプリケーションをブロックすることがあります。

ソケットのオプションSO_SNDBUFを増やしてみてください。ブロッキングを避けたい場合は、最大のSendLength値より大きい値にしてください。 setsockopt()を使用すると、SO_SNDBUFの値を変更できます。

関連する問題