19

私はC++でRTSPソースフィルターを開発しており、WINSOCK2.0-ブロッキングソケットを使用しています。

ブロッキングソケットを作成するときは、次のSO_RCVTIMEOように3秒に設定します。

int ReceiveTimeout = 3000; 
int e = setsockopt(Socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&ReceiveTimeout, sizeof(int));

フィルタが接続しようとしIP_ADDRESS:554ます(554はRTSPサーバーポートです)。ポート554でそのIPをリッスンしているサーバーがある場合、すべてうまくいきますが、次のようになります。

  1. 私のフィルターが既存のIPアドレスへのソケットを作成するが、誰もリッスンしていないランダムなポートで、connect()3秒間待機し、を返す場合WSAETIMEDOUT。したがって、3秒後、提供されたURLが不正であることがわかります。

  2. フィルタが存在しないIPアドレスへのソケットを作成し、それを接続しようとすると、SOCKET_ERRORを返す前に約10秒間ハングします。したがって、SO_RCVTIMEOIPがネットワーク上に存在しない場合は無視されます...

質問: 2番目のケースでは、存在しないIPのタイムアウトを設定するにはどうすればよいですか?IPが存在するかどうかを確認するために最初にICMPPINGを送信する必要がありますか、それともそのような他のチェックを実行する必要がありますか?

どんな助けでもありがたいです。ありがとう。:)

私の問題への答え

私はブロッキングソケットを使用しているのでconnect()、接続が確立されるまで、またはホストが応答していないか、接続を拒否しているために接続が失敗するまで、ブロックを呼び出します。ソケットのタイムアウトを3秒に設定し、存在しないホストに接続しようとすると、PC(クライアント)はSYNフラグが設定されたTCPパケットを送信して、スリーウェイハンドシェイクを開始します。通常、ホストは、起動している場合、フラグが設定されたTCPパケットで応答しACKSYNクライアント(me)はACKフラグが設定されたTCPパケットを送信します。次に、接続が確立されます。ただし、ホストがダウンしてSYN送信された場合、クライアントは3秒のタイムアウトが期限切れになるまで待機してから、TcpMaxConnectRetransmissionsMICROSOFT ARTICLE)ホストは稼働している可能性がありますが、パケットが失われる可能性があるため、レジストリ設定に到達しますSYN...私のWindows XPではこの設定が4になっていると思います。したがって、送信を試みるたびにSYN3秒待機し、4番目のときはtryは失敗し、SOCKET_ERROR(12秒後に)戻りWSAETIMEDOUT、最後のWSAエラーとして設定されます。

connect()これを回避する方法は、非ブロッキングソケットを使用し、Martin Jamesが提案したように、接続試行時間を手動で測定しようとすることです(現在はブロックされないため)。

もう1つの方法は、レジストリをいじることです。これが最後の手段です...

4

3 に答える 3

2

弾丸を噛みます。リモート IP で PING サーバーが実行されていないか、PING が一部のルーターによってブロックされている可能性があるため、役に立ちません。10秒待ってから、使用するエラー表示を行うことはできませんか?

試行された接続を 3 秒後にタイムアウトする必要がある場合は、自分でタイムアウトできます。

于 2011-06-01T09:48:32.233 に答える
1

実は、Berkeley ソケットには接続のタ​​イムアウトがないため、設定することはできません。ICMP PING は役に立ちません。理由はわかりませんが、ホストが存在しない場合は、PING で約 1 秒を費やします。ホストが存在するかどうかを検出するために ARP を使用してみてください。

于 2011-06-01T10:35:51.550 に答える
-1

cmd から、「ping -w 100 -n 1 192.168.1.1」のようなタイムアウトで IP に ping を実行できます

100mS以内に戻ります

'echo %errorlevel% 0 = OK、1 = 失敗で戻りコードを確認できます。接続を試みる必要があるかどうかがわかります。

C++で

bool pingip_nowait(const char* ipaddr)
{
    DWORD exitCode;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput =  GetStdHandle(STD_OUTPUT_HANDLE);
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    si.wShowWindow = SW_HIDE;

    CString cmd = "ping -w 100 -n 1 ";
    cmd += ipaddr;
    if (!CreateProcess(NULL,
        cmd.GetBuffer(),
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi)) {
            TRACE("ERROR: Cannot launch child process\n");
            return false;
    }

    // Give the process time to execute and finish
    WaitForSingleObject(pi.hProcess, 200L);

    if (GetExitCodeProcess(pi.hProcess, &exitCode))
    {
        TRACE("ping returned %d\n", exitCode);
        // Close process and thread handles. 
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
        return exitCode==0 ? true : false;
    }
    TRACE("GetExitCodeProcess() failed\n");
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return false;
} 
于 2013-04-04T08:37:51.217 に答える