1

リモートサーバーに接続しているときに、アプリケーションがTCP経由で切断を検出する方法を見つけようとしています。これを行うための明白な方法は、TCPキープアライブオプションを使用することだと思っていました。これはMFCC++アプリケーションであり、MySockクラスはCSocketから継承します。Connectの呼び出しの前後にSO_KEEPALIVEオプションを設定しようとしましたが、キープアライブパケットがwireshark経由で送信されるのを見たことがありません。接続で送信しているすべてのデータを正常に確認できるので、接続されて機能していることがわかります。

if (!(m_connection = new MySock(this)))
{
    AfxMessageBox ("Failed to allocate socket! Close and restart app.");
    m_connect.EnableWindow(true);
    return false;
}

if (!m_connection->Create())
{
    AfxMessageBox ("Failed to create client socket! Close and restart app.");
    m_connect.EnableWindow(true);
    return false;
}

TCHAR buff[128];
DWORD optval = true;
int temp = sizeof(DWORD);

if (!m_connection->GetSockOpt(SO_KEEPALIVE, (void*)&optval, &temp, SOL_SOCKET))
{
    wsprintf (buff, "GetSockOpt Error %d", GetLastError());
    AfxMessageBox (buff);
}

wsprintf (buff, "GetSockOpt %d", optval);
AfxMessageBox (buff);

optval = true;
temp = sizeof(DWORD);
if (!m_connection->SetSockOpt(SO_KEEPALIVE, (void*)&optval, temp, SOL_SOCKET))
{
    wsprintf (buff, "SetSockOpt Error %d", GetLastError());
    AfxMessageBox (buff);
}

optval = false;
temp = sizeof(DWORD);
if (!m_connection->GetSockOpt(SO_KEEPALIVE, (void*)&optval, &temp, SOL_SOCKET))
{
    wsprintf (buff, "GetSockOpt Error %d", GetLastError());
    AfxMessageBox (buff);
}

wsprintf (buff, "GetSockOpt %d", optval);
AfxMessageBox (buff);

CString consoleText;

m_console.GetWindowText(consoleText);

consoleText += "Control Connected!\r\n";

m_console.SetWindowText(consoleText);

if (!m_connection->Connect(address, CONTROL_PORT))
{
    AfxMessageBox ("Failed to connect");
    m_connection->Close();
    delete m_connection;
    m_connection = NULL;
    m_connect.EnableWindow(true);
    return false;
}

optval = false;
temp = sizeof(DWORD);
if (!m_xcmp->GetSockOpt(SO_KEEPALIVE, (void*)&optval, &temp, SOL_SOCKET))
{
    wsprintf (buff, "GetSockOpt Error %d", GetLastError());
    AfxMessageBox (buff);
}
wsprintf (buff, "GetSockOpt %d", optval);
AfxMessageBox (buff);

SetSockOptを呼び出す前にGetSockOptを呼び出したときのoptvalの値は0であり、呼び出した後の値は1です。接続後の値も1に設定されています。GetSockOptを呼び出す前にoptvalを0に設定して、何も変わっていないことを確認しました。GetまたはSetのいずれもエラーを返していません。どんな助けやアイデアもいただければ幸いです。私の現在の理論は、クライアント側の接続(私はリスニングソケットに接続しています)はキープアライブを送信しないというものです。キープアライブは、リスナーであった接続からのみ発生しますか?御時間ありがとうございます。

4

2 に答える 2

1

setsockopt() は「keep-alive」オプションを有効/無効にすることしかできず、デフォルトの TCP キープアライブ タイムアウトは 7200 秒です。WSAIoctl() | を見てください。SIO_KEEPALIVE_VALS、キープアライブのタイムアウトと間隔も変更できます。

于 2011-08-06T09:37:11.197 に答える
1

デフォルトの TCP キープアライブ タイムアウトは 7200 秒、つまり2 時間です。このタイムアウトは通常sysctl(8)、Unix で制御されます。Windows には、おそらくこれ用のレジストリ キーがいくつかありますがKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters、私にはわかりません。ここでは、TCP キープアライブ メカニズムの概要を簡単に説明します。

これはあまり役に立たないことにも注意してください。アプリケーション プロトコルにある種のハートビート メカニズムを実装して、切断されたピアだけでなく、遅延やスタックしているピアも検出する方がはるかに優れています。

于 2011-08-05T13:58:13.433 に答える