MFC CSocket пакеты keepalive не отправляются - PullRequest
1 голос
/ 05 августа 2011

Я пытаюсь найти способ для моего приложения обнаруживать разрывы соединения через TCP при подключении к удаленному серверу.Я думал, что очевидный способ сделать это - использовать опцию keepalive TCP.Это приложение MFC C ++, а класс MySock наследуется от CSocket.Я попытался установить параметр SO_KEEPALIVE до и после вызова Connect, и я никогда не видел, чтобы пакет 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);

Значение optval при вызове GetSockOpt до вызова SetSockOpt равно 0, а после вызова - 1.Также значение после подключения по-прежнему установлено в 1. Я установил optval в 0, прежде чем вызывать GetSockOpt, просто чтобы быть уверенным, что ничего странного не происходит.Ни один из Get или Set не возвращает ошибок.Любая помощь или идеи будут оценены.Моя текущая теория заключается в том, что клиентские соединения (я подключаюсь к сокету Listening) не отправляют сообщения активности.Keepalive приходят только от связи, которая была слушателем?Спасибо за ваше время.

Ответы [ 2 ]

1 голос
/ 06 августа 2011

setsockopt () может только включать / отключать опцию «keep-alive», а тайм-аут TCP-активности по умолчанию составляет 7200 секунд.Посмотрите на WSAIoctl () |SIO_KEEPALIVE_VALS, он также может изменить время ожидания и интервал поддержания активности.

1 голос
/ 05 августа 2011

Тайм-аут активности TCP по умолчанию составляет 7200 секунд, то есть два часа , так что вам придется ждать так много, чтобы увидеть что-либо из этого в действии. Этот таймаут обычно контролируется с помощью sysctl(8) в Unix, Windows, вероятно, имеет какой-то раздел реестра под KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters, я понятия не имею. Вот краткий обзор механизма TCP KeepAlive .

Позвольте мне также отметить, что это не очень полезно. Было бы гораздо лучше внедрить в протокол приложения своего рода механизм биения, чтобы обнаруживать не только отключенные, но и запаздывающие и зависшие одноранговые узлы.

...