MFC CSocket keepalive数据包不发送

时间:2011-08-05 13:32:27

标签: sockets visual-c++ mfc mfc-networking

我正在尝试为我的应用程序找到一种方法,以便在连接到远程服务器时通过TCP检测断开连接。我认为显而易见的方法是使用TCP keepalive选项。这是一个MFC C ++应用程序,MySock类继承自CSocket。我已经尝试在调用Connect之前和之后设置SO_KEEPALIVE选项,我从未见过通过wireshark发送的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);

在调用SetSockOpt之前调用GetSockOpt时optval的值为0,并在调用它之后为1.连接后的值仍然设置为1.我在调用GetSockOpt之前将optval设置为0只是为了确保没有发生任何奇怪的事情。 Get或Set都没有返回错误。任何帮助或想法将不胜感激。我目前的理论是客户端连接(我连接到侦听套接字)不发送keepalive。 Keepalive只来自一个听众的联系吗?谢谢你的时间。

2 个答案:

答案 0 :(得分:1)

默认的TCP保持活动超时为7200秒,即两小时,因此您必须等待那么多才能看到其中的任何一个。这个超时通常在Unix上用sysctl(8)控制,Windows可能在KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下有一些注册表项,我不知道。这是一个简短的overview of the TCP KeepAlive mechanism

我还要指出,这不是非常有用。你应该在应用程序协议中实现某种心跳机制,以便不仅检测断开连接,而且还检测滞后和卡住的对等体。

答案 1 :(得分:1)

setsockopt()只能启用/禁用'keep-alive'选项,默认的TCP保持活动超时为7200秒。 看看WSAIoctl()| SIO_KEEPALIVE_VALS,它还可以更改保持活动超时和间隔。