Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

心跳包在长连接中的必要性

  由于HTTP是基于TCP的,所以TCP上存在的问题HTTP当然也会存在。TCP虽然说是面向连接的,但是所谓的“连接”只是抽象出来的而已,真正连接两台电脑的是物理网络。如果没有心跳包持续不断的告诉服务器连接状态是可用的,服务器就无法判断连接的可用性。
  当客户端正常关闭TCP连接时,会发送一个关闭数据包到服务器,告诉服务器自己已断开。但是未必所有连接都是正常断开的,经常会有很多突发状况,比如程序错误或网络中断。这就会导致服务器无法得到客户端的关闭信息,从而产生大量的死连接。
  其实TCP上使用心跳包已经成为了很普遍的现象,所以TCP上的问题很快就得到了解决。但是HTTP上的问题就不容易解决了,虽然TCP请求是可以正确断开,但是HTTP服务器中执行的程序和管理TCP的程序未必是同一个。比如HTTP请求的页面程序用PHP来执行,而请求本身的TCP连接在Apache上管理。这样即使客户端断开了连接也无法传达到PHP中,这就会遇上和无心跳包TCP一样的问题。比如下面这个程序 set_time_limit(0);
while(1){
  sleep(1);
  touch('running');
};
  在这个程序中我并没有设置“ignore_user_abort”,但是这个程序一旦运行就无法停止,只能重启Apache。可以试着调用“connection_status”来获取当前连接的状态,但是即使浏览器已经关闭,PHP也依然认为连接状态是可用的。因为中间多了个Apache!层次多了命令就变味了,这也是为什么党中央的命令下达到地方时总是变味的原因。怎么办?和TCP的解决办法一样,用个心跳包来增强巩固深入贯彻落实PHP程序与客户端的联系。
ob_end_clean();
set_time_limit(0);
while(1){
  sleep(1);
  echo "\0";
  flush();
  touch('running');
};
  这样,每次循环都会发送一个零字符到客户端,如果发送不成功PHP就能马上察觉到客户端是断开的,从而把自己也停止掉。如果PHP默认开启了ob注意关闭它或者在“flush”之前调用“ob_flush”,要不然零字符无法发送到客户端。这里的零字符只是一个例子,可以根据需求换成其它字符。比如如果你的数据是JSON,那就最好换成空格。因为空格不影响JSON,而零字符会让JSON解析错误。
  除非你的程序可以直接管理TCP,比如NodeJS之类的。否则在使用长连接时都应该给程序加上一个心跳包的功能。
网名:
3.84.186.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^