TCP长连接保持连接状态TCP keepalive设置
转载:http://blog.csdn.net/embedded_sky/article/details/42077321
对于TCP长连接保活是十分必要的,原因如下:
1、系统多在OA网和外网间有防火墙隔离,很多防火墙对一段时间内没有报文活动的socket会自动关闭。
2、对于非正常断开的连接系统并不能侦测到,比如防火墙关闭端口、网线被拔掉、电脑突然奔掉、未关闭应用程序直接关机(服务端无法释放资源)。
(调用close(fd)为正常断开,连接对端可以侦测到)
TCP长连接保持的两种办法:
1) 应用层面的心跳机制
自定义心跳消息头.,一般客户端主动发送到服务端,服务器接收后进行回应(也可以不回应),以便能够侦测连接是否异常断开。
2) TCP协议自带的保活功能
通过设置TCP keepalive的属性,打开socket的keepalive属性,并设置发送底层心跳包的时间间隔。TCP/IP五层网络模型,我们调用socket等接口是应用层的函数,TCP keepalive是在底层定时发送心跳报文,服务器端接收到底层的心跳报文直接丢弃,不关心其内容。
使用TCP keepalive来保持长连接状态显然要舒服一些,直接调用系统的API即可实现,对于系统而言负担也更轻(相对第一种办法)。
以下是windows下TCP keepalive设置的函数:
1 /*@author super bert 2014-12-16*/ 2 /*socket TCP保持长连接函数*/ 3 int socket_tcp_alive(int socket) 4 { 5 int ret = 0; 6 7 int keep_alive = 1; 8 ret = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&keep_alive, sizeof(keep_alive)); 9 10 if (ret == SOCKET_ERROR) 11 { 12 printf("setsockopt failed: %d \n", WSAGetLastError()); 13 return -1; 14 } 15 16 struct tcp_keepalive in_keep_alive = {0}; 17 unsigned long ul_in_len = sizeof(struct tcp_keepalive); 18 struct tcp_keepalive out_keep_alive = {0}; 19 unsigned long ul_out_len = sizeof(struct tcp_keepalive); 20 unsigned long ul_bytes_return = 0; 21 22 in_keep_alive.onoff = 1; /*打开keepalive*/ 23 in_keep_alive.keepaliveinterval = 5000; /*发送keepalive心跳时间间隔-单位为毫秒*/ 24 in_keep_alive.keepalivetime = 1000; /*多长时间没有报文开始发送keepalive心跳包-单位为毫秒*/ 25 26 ret = WSAIoctl(socket, SIO_KEEPALIVE_VALS, (LPVOID)&in_keep_alive, ul_in_len, 27 (LPVOID)&out_keep_alive, ul_out_len, &ul_bytes_return, NULL, NULL); 28 29 if (ret == SOCKET_ERROR) 30 { 31 printf("WSAIoctl failed: %d \n", WSAGetLastError()); 32 return -1; 33 } 34 35 return 0; 36 }