2016-02-09 6 views
1

Мы ищем способ включения TCP keepalive для клиентских сокетов в Windows CE 6.0 с использованием .net Compact framework 3.5.Включить Tcp Keepalive в Windows CE 6.0

До сих пор я нашел эти варианты:

Набор KeepAlive с использованием SetSocketOption на классе System.Net.Socket:

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); 

Это на самом деле работает, но использует Windows-глобальные настройки для KeepAlive , и это нужно проверить соединение каждый второй час, что слишком редко для нашего случая использования. Этот параметр таймаута можно изменить (глобально), изменив разделы реестра в разделе [HKEY_LOCAL_MACHINE \ Comm \ Tcpip \ Parms]. Это будет мое резервное решение, но я предпочел бы установить тайм-ауты для каждого соединения.

Затем я попытался использовать socket.IoControl, как предложено несколькими источниками в Интернете, чтобы установить эту опцию сокета, включая значения тайм-аута, но это приводит только к SocketException («Неверный аргумент был предоставлен»).

Пример

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

// The native structure for this is defined in mstcpip.h as: 
//struct tcp_keepalive { 
//u_long onoff; 
//u_long keepalivetime; 
//u_long keepaliveinterval; 
//}; 

//Set to on, 10 seconds and 1 second. From examples online u_long should be interpreted as unsigned 32bit. 
byte[] inValue = new[] { (uint)1, (uint)10000, (uint)1000 } 
.SelectMany(x => BitConverter.GetBytes(x)) 
.ToArray(); 

//0x98000004 is constant for SIO_KEEPALIVE_VALS found in mstcpip.h 
int ioControlCodeKeepAliveValues = BitConverter.ToInt32(BitConverter.GetBytes(0x98000004), 0); 

// Throws "An invalid argument was supplied" SocketException 
socket.IOControl(ioControlCodeKeepAliveValues, inValue, null); 

socket.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.120"),80)); 

Является ли этот код правильно, или это известное ограничение Windows CE 6, поддержания активности не может быть установлен в связи с этим?

ответ

1

Это было какое-то время, но я тоже посмотрел на это. В конце концов я решил, что возиться с реестром будет не переносимым и легко забыть при установке на новую машину. Я не могу вспомнить, что я пробовал, но я помню, что это было довольно утомительно и в итоге не создавало удовлетворительного решения. Я думаю, что было несколько случаев, когда некоторые API-запросы в документах выглядели как правильные вещи, но оказались пустой тратой времени. Я должен отметить, что я был на Windows Server, а не на CE.

В конце концов, я реализовал keep-alive вручную, то есть, отправив что-то через соединение. Это довольно легко сделать, поскольку вы можете просто использовать поток с низким приоритетом, делая это время от времени.

0

Кроме того, вы должны помнить, что встроенный механизм Keep-Alive TCP также не очень надежный. Пройдя много статей (например, от Cisco), я заметил, что у вас нет гарантий, что сетевые устройства будут передавать TCP-пакеты с длиной 0, что в основном является пакетом Keep-Alive. Даже TCP RFC призвал не использовать это решение:

Implementors MAY include "keep-alives" in their TCP implementations, although this practice is not universally accepted. If keep-alives are included, the application MUST be able to turn them on or off for each TCP connection, and they MUST default to off.

Так длинный рассказ короткий - когда Keep-Alive получен, вы знаете связь, но когда он не делает - вы ничего не знаете. Очень похоже на Джона Сноу.

На мой взгляд, лучшее решение уже опубликовано - вы можете добавить еще один поток на каждом конце, который только слушает ваши собственные Keep-Alive (или любые) пакеты и сообщает вам, когда что-то пойдет не так.

+0

Решение для добавления биения на уровне приложения является опцией, когда вы контролируете протокол приложения, но в этом случае у меня этого нет, и сервер не будет хорошо реагировать на меня, отправляя дополнительные данные в сокет I 'Боюсь. Вот почему я на уровне TCP. –

+0

Так что, боюсь, вы в этом случае проиграли. Как я уже упоминал, встроенный keep-alive работает только иногда и не является надежным. Надеюсь, вы найдете другое решение :) – badsamaritan

0

У меня нет доступа к CE6.0 устройства на данный момент, но код, как показано

  • работ по CE7.0 (IOControl вызов завершается успешно)
  • не работает на CE5.0 (броски SocketException)

Поэтому мое предположение было бы, что SIO_KEEPALIVE_VALS просто не поддерживается на CE6.0.

Как и в сторону, а не вызывать BitConverter дважды, код IOCTL может быть получен следующим образом:

int ioctl; 
unchecked { ioctl = (int)0x98000004; } 

Лично я нахожу это более читаемым, но опять-таки не все любят непроверенные блоки и бросает в коде ,

+0

Пока WSAIoctl (SIO_KEEPALIVE_VALS) возвращает 0, что означает успех, но пакеты TCP Keepalive не отправляются (протестированы в Wireshark). –

0

Я только что попробовал использовать код SIO_KEEPALIVE_VALS для функции WSAIoctl() из моего приложения Windows CE 7. Хотя WSAIoctl (SIO_KEEPALIVE_VALS) возвращает 0, что означает успех, но пакеты TCP Keepalive не отправляются (тестируются в Wireshark). Таким образом, код кажется не работает на Windows CE.

Похоже, что параметры Keep-alive (время, период и количество) в системном реестре, а затем включение Keepalive для сокета в коде приложения является единственным решением в Windows CE.

Или просто используйте какой-то другой, более надежный механизм detecting broken connections, как сообщения с сердечным ритмом.

Смежные вопросы