`
kevin.wang
  • 浏览: 243543 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于TCP、UDP、及keep_alive属性的总结

    博客分类:
  • Tech
阅读更多
【问题原由】:
进行长连接通信时(如移动应用开发中手机端与服务端要维持一个稳定的连接,进行实时消息传递),需要在应用层定义心跳机制。有人问,TCP本身就是可靠传输协议,为什么还需要应用层来实现心跳机制呢?

【明确定义】
TCP的可靠传输是相对于UDP而言,
UDP在传输数据之前不需要先建立连接,远地主机的运输层在接收到UDP报文后,不需要确认。
TCP提供面向连接服务,传输数据前必须三次握手建立连接,接收方确认,四次挥手释放链接,
TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
【然而】在使用TCP建立连接后
1) 很多防火墙等对于空闲socket自动关闭
2) 对于非正常断开, 服务器并不能检测到(如拔网线,直接关机等).

【解决办法--keepalive属性】
套接字本身是有一套心跳保活机制的,不过默认的设置并不像我们一厢情愿的那样有效。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

很多人认为两个小时的时间设置得很不合理。为什么不设置成为10分钟,或者更短的时间?(可以通过SO_KEEPALIVE选项设置。)但是这样做其实并不被推荐。实际上这套机制只是操作系统底层使用的一个被动机制,原理上不应该被上层应用层使用。当系统关闭一个由KEEPALIVE机制检查出来的死连接时,是不会主动通知上层应用的,只有在调用相应的IO操作在返回值中检查出来。
因此,忘记SO_KEEPALIVE,在应用层自己写一套保活机制比较靠谱


如果实在没办法,懒省事等等其他原因,就先设置keepalive吧
【如何设置keepalive】
1)代码设置
除了keepAlive 开关, 还有keepIdle, keepInterval, keepCount 3个属性, 使用简单, 如下:
int keepAlive = 1;   // 开启keepalive属性. 缺省值: 0(关闭) 
int keepIdle = 60;   // 如果在60秒内没有任何数据交互,则进行探测. 缺省值:7200(s) 
int keepInterval = 5;   // 探测时发探测包的时间间隔为5秒. 缺省值:75(s) 
int keepCount = 2;   // 探测重试的次数. 全部超时则认定连接失效..缺省值:9(次) 
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive)); 
setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); 
setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval)); 
setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount)); 


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


引用http://blog.csdn.net/aa2650/article/details/17027845总结的特别好
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics