2011-08-05 52 views
1

我正試圖找到一種方法,當我連接到遠程服務器時,我的應用程序可以通過TCP檢測斷開連接。我正在考慮明顯的做法是使用TCP keepalive選項。這是一個MFC C++應用程序,MySock類繼承自CSocket。我曾嘗試在調用Connect之前和之後設置SO_KEEPALIVE選項,並且我從未見過通過wireshark發送Keepalive數據包。我可以看到我在連接上發送的所有數據,因此我知道它已連接並正在工作。MFC CSocket Keepalive數據包不發送

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

調用的getsockopt時之前調用setsockopt的是0 optval的,並呼籲它是1。而且連接後的值調用的getsockopt只是要確保沒有之前仍然設置爲1。我設置optval的爲0後的值奇怪的事情正在發生。 Get或Set都不返回錯誤。任何幫助或想法,將不勝感激。我目前的理論是,客戶端連接(我連接到偵聽套接字)不會發送Keepalive。 Keepalive是否只來自於聽衆的聯繫?謝謝你的時間。

回答

1

默認TCP保持活動超時時間爲7200秒,即兩小時,因此您必須等待很長時間才能看到其中的任何動作。這種超時通常在Unix上由sysctl(8)控制,Windows可能在KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下有一些註冊表項,對此我不知道。這是一個簡短的overview of the TCP KeepAlive mechanism

讓我也注意到,這不是非常有用。在應用程序協議中實現某種心跳機制可以更好地檢測不僅斷開連接,而且還可以檢測滯後和卡住的對等體。

+0

非常感謝你釘了它。這些功能實際上並非我正在仔細檢查的內容。當我在這裏工作了幾天後,在這裏問了幾分鐘之後,我就會遇到這種情況,經常會發生LOL。我認爲這個功能每隔幾秒鐘就像一個ping機制,但這不是它的目的。 – ThePosey

1

setsockopt()只能啓用/禁用'keep-alive'選項,並且默認的TCP保持活動超時時間爲7200秒。 看看WSAIoctl()| SIO_KEEPALIVE_VALS,它也可以更改保持活動超時和間隔。