上周使用华为4G网络发现程序在掉线重新拨号后socket不能连接,经过检查发现是重新拨号后ip发生变化,但是socket状态还是返回正常,造成判断错误,因为服务端需要面对不同的程序,所以在socket加入keepalive检测,需要注意是keepaliv设置检测时间一定要不应用程序定时发送数据的时间短,否则keepalive不会检测。参考网络文章进行修改
keepalive默认是关闭的, 因为虽然流量极小, 毕竟是开销. 因此需要用户手动开启. 有两种方式开启.
1) 在代码里针对每个socket进行单独设定, 使用起来灵活.
除了keepAlive 开关, 还有keepIdle, keepInterval, keepCount 3个属性, 使用简单, 如下:
int keepalive = 1; // 开启keepalive属性
int keepidle = 20; // 如该连接在20秒内没有任何数据往来,则进行探测
int keepinterval = 5; // 探测时发包的时间间隔为5 秒
int keepcount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.
setsockopt(pSocket->m_sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive ));
setsockopt(pSocket->m_sockfd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle ));
setsockopt(pSocket->m_sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval ));
setsockopt(pSocket->m_sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount ));
使用时需要#include <netinet/tcp.h>, 否则SOL_TCP和TCP_KEEPIDLE等3个宏找不到.
2) 修改配置文件, 对整个系统所有的socket有效.
我们可以用cat命令查看到系统中这几个默认的值.
#cat /proc/sys/net/ipv4/tcp_keepalive_time 7200
#cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75
#cat /proc/sys/net/ipv4/tcp_keepalive_probes 9
修改它们:
#echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time
#echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl
#echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
若想保存设置可以在etc下修改sysctl.conf加入下面内容
net.ipv4.tcp_keepalive_intvl = 3
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 20
意 思就是说对于tcp连接,如果一直在socket上有数据来往就不会触发keepalive,但是如果20秒一直没有数据往来,则keep alive开始工作:发送探测包,受到响应则认为网络,是好的,结束探测;如果没有相应就每隔3秒发探测包,一共发送3次,3次后仍没有相应,