一、什么是Keep-Alive模式?
我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
http 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;http 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。
二、代码使用
SetKeepAliveValues 方法启用或禁用 TCP 保持选项指定的 TCP 保持超时和间隔用于保持 TCP 数据包的每个连接设置。保持选项的详细信息,请参阅 4.2.3.6 节要求的互联网 HostsCommunication 图层在 IETF 网站上可用的 RFC 1122 中指定。
optionInValue 参数,传递给 Socket.IOControl 应指向 Mstcpip.h 头文件中定义的 tcp_keepalive 结构。这种结构的定义如下:
1 /* Argument structure for SIO_KEEPALIVE_VALS */ 2 struct tcp_keepalive { 3 u_long onoff; 4 u_long keepalivetime; 5 u_long keepaliveinterval; 6 };
将 tcp_keepalive C 转换为 C# struct结构
1 // Convert tcp_keepalive C struct To C# struct 2 [ 3 System.Runtime.InteropServices.StructLayout 4 ( 5 System.Runtime.InteropServices.LayoutKind.Explicit 6 ) 7 ] 8 unsafe struct TcpKeepAlive 9 { 10 [System.Runtime.InteropServices.FieldOffset(0)] 11 [ 12 System.Runtime.InteropServices.MarshalAs 13 ( 14 System.Runtime.InteropServices.UnmanagedType.ByValArray, 15 SizeConst = 12 16 ) 17 ] 18 public fixed byte Bytes[12]; 19 20 [System.Runtime.InteropServices.FieldOffset(0)] 21 public uint On_Off; 22 23 [System.Runtime.InteropServices.FieldOffset(4)] 24 public uint KeepaLiveTime; 25 26 [System.Runtime.InteropServices.FieldOffset(8)] 27 public uint KeepaLiveInterval; 28 } 29 30 public int SetKeepAliveValues 31 ( 32 System.Net.Sockets.Socket Socket, 33 bool On_Off, 34 uint KeepaLiveTime, 35 uint KeepaLiveInterval 36 ) 37 { 38 int Result = -1; 39 40 unsafe 41 { 42 TcpKeepAlive KeepAliveValues = new TcpKeepAlive(); 43 44 KeepAliveValues.On_Off = Convert.ToUInt32(On_Off); 45 KeepAliveValues.KeepaLiveTime = KeepaLiveTime; 46 KeepAliveValues.KeepaLiveInterval = KeepaLiveInterval; 47 48 byte[] InValue = new byte[12]; 49 50 for (int I = 0; I < 12; I++) 51 InValue[I] = KeepAliveValues.Bytes[I]; 52 53 Result = Socket.IOControl(IOControlCode.KeepAliveValues, InValue, null); 54 } 55 56 return Result; 57 }
调用方法:
1 System.Net.Sockets.Socket Socket = new System.Net.Sockets.Socket 2 ( 3 System.Net.Sockets.AddressFamily.InterNetwork, 4 System.Net.Sockets.SocketType.Stream, 5 System.Net.Sockets.ProtocolType.Tcp 6 ); 7 8 // Set 10 Hours: 10 * 60 * 60 * 1000 = 36,000,000 every 1 Second 1000 9 SetKeepAliveValues(Socket, true, 36000000, 1000);