Un cliente mi ha chiesto di attivare il keepAlive su un socket in un applicativo c#, così su due piedi ho detto: Facile ! Basta usare:
1: private TcpListener listener;
2: listener.Server.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1);//per abilitare il tcpkeepalive sul socket
Però il settaggio sopra serve solo per attivare il keepAlive su un socket utilizzando i valori di default da settare nel registry:
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters]
KeepAliveTime = millisecondi
Specifica l’idle time in millisecondi prima che il TCP cominci ad inviare keepalive. Default 2 ore (7.200.000)
KeepAliveInterval = uint
Specifica l’intervallo in secondi tra le ritrasmissioni dei keepalive dopo che il KeepAliveTime è scaduto. Default 1 secondo (1)
Purtroppo il requisito del cliente era quello di settare differenti intervalli di KeepAlive e quindi ho dovuto prendere un approccio leggermente più complesso che ho trovato dopo una bella sessione di Google:
1: private TcpListener listener;
2: SetTcpKeepAlive(listener.Server, 5000, 1);
3: listener.Server.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1);// per abilitare il keepalive
4:
5: public static void SetTcpKeepAlive(Socket socket, uint keepaliveTime, uint keepaliveInterval)
6: {
7: /* the native structure
8: struct tcp_keepalive {
9: ULONG onoff;
10: ULONG keepalivetime;
11: ULONG keepaliveinterval;
12: };
13: */
14:
15: // marshal the equivalent of the native structure into a byte array
16: uint dummy = 0;
17: byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
18: BitConverter.GetBytes((uint)(keepaliveTime)).CopyTo(inOptionValues, 0);
19: BitConverter.GetBytes((uint)keepaliveTime).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
20: BitConverter.GetBytes((uint)keepaliveInterval).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
21:
22: // write SIO_VALS to Socket IOControl
23: socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
24: }
In questo modo è possibile settare i valori di KeepAlive su singolo socket.