6

winsock の recv() ループで問題が発生しています。iResult==0 のときにループを終了しようとしていますが、ループはソケットが閉じたときにのみ終了します。iResult が 0 になる最後の recv() でハングしているようです。ループを効果的に終了する方法について何かアイデアはありますか? 私の最終的な目標 (iResult == 0 であるかどうかに関係なく、おそらくこれについて間違った方法で行っている可能性があります) は、送信されたすべての情報が読み取られたときにループを停止することです。これがループです。

    do
    {
        iResult = recv(socket, recvbuf, BUFLEN-1, 0);
        if(iResult > 0){
            // Null byte :)
            // Remove that garbage >:(
            recvbuf[iResult] = '\0';
            printf("Recvbuf: %s\n\n\niResult: %d\n",recvbuf,iResult);
            continue; // working properly
        }
        else if(iResult == 0)
            // Connection closed properly
            break;
        else
        {
            printf("ERROR! %ld",WSAGetLastError());
            break;
        }
    } while(iResult > 0);

私が言ったように、私はすべてのデータを受け取っていますが、ループを終了できません。次のステップは、データをサーバーに書き戻すことですが、ping タイムアウトまでここでハングします。ソケットは SOCK_STREAM で、BUFLEN は 0x200 として定義されています

ありがとう

4

2 に答える 2

4

デフォルトでは、0を返す代わりに、recv 受信するデータがない場合はブロックします

ソケットで使用可能な着信データがない場合、recv呼び出しは、ソケットが非ブロッキングでない限り、MSG_PARTIALフラグが設定されていないWSARecvに対して定義されたブロッキング規則に従って、データがブロックされて到着するのを待ちます。この場合、エラーコードをWSAEWOULDBLOCKに設定してSOCKET_ERRORの値が返されます。select、WSAAsyncSelect、またはWSAEventSelect関数を使用して、さらにデータが到着するタイミングを判別できます。

ioctlsocketを使用して、ソケットを非ブロッキングモードにすることができます。

u_long iMode = 1;
ioctlsocket(socket, FIONBIO, &iMode);

編集:これは私が以前のリビジョンで作成し、その後削除したsetsockoptの提案です(コメントを参照):

データが利用できない場合にソケットをタイムアウトに設定するオプションを指定して、setsockopt 関数を使用できます。SO_RCVTIMEOrecv

于 2010-07-27T02:37:55.350 に答える
1

TCP 通信メカニズムを設計するときは、メッセージ境界を定義する必要があります。(多くの場合 \r\n)。それ自体では、tcp は境界について認識していません。あなたはこれを自分でしなければなりません。recv() 呼び出しは、常にメッセージ境界に戻るとは限りません。1 つの send() が、反対側で複数の recv()-s に分割される場合があります。

于 2010-07-27T03:35:42.887 に答える