2011-08-05 42 views
1

リモートサーバーに接続しているときに、TCP経由でアプリケーションを検出する方法を見つけようとしています。私はこれを行う明白な方法がTCPキープアライブオプションを使用することだと考えていました。これはMFC C++アプリケーションであり、MySockクラスはCSocketから継承します。私は接続の前と後にSO_KEEPALIVEオプションを設定しようとしましたが、キープアライブパケットがwireshark経由で送信されるのを見たことがありません。私はそれが接続され、動作していることを知っているので、私が接続上で送信しているすべてのデータを見ることができます。MFC CSocketキープアライブパケットが送信されない

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); 

はoptvalの値のsetsockoptを呼び出す前にGETSOCKOPTの呼び出しは0で、接続後の値がまだ1に設定されている。また1である、それを呼び出した後、私は念の何もないようにGETSOCKOPTを呼び出す前に0にはoptval設定奇妙なことが起こっていた。 GetまたはSetのいずれもエラーを返すことはありません。どんな助けやアイデアも感謝します。私の現在の理論は、クライアント側の接続(私はリスニングソケットに接続している)がキープアライブを送信しないということです。キープアライブは、リスナーであった接続からのみ取得されますか?御時間ありがとうございます。

答えて

1

既定のTCPキープアライブタイムアウトは7200秒です。すなわち、2時間です。そのため、実際の動作を確認するにはそれほど待たなければなりません。このタイムアウトは通常Unixではsysctl(8)で制御されていますが、WindowsにはおそらくKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parametersの下にいくつかのレジストリキーがありますが、わかりません。ここに簡略overview of the TCP KeepAlive mechanismがあります。

これはあまり役に立ちません。あなたはだけでなく、切断を検出するためのアプリケーションプロトコルでハートビートメカニズムのいくつかの並べ替えを実装するだけでなく、遅れてオフはるかに良いとピアを立ち往生と思います。

+0

ありがとうございました。機能性は、私が精密な検査で探しているものではありません。もちろん、私はLOLが常に起こる数日のために、この作業を終えた後、ここで求めた後、このほんの数分に出くわしました。私は、これはピング・メカニズムのように、数秒ごとに機能を考えていたが、それはそれはのために何ではありません。 – ThePosey

1

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

関連する問題