本文是我在实际工作中用到的Socket通信,关于心跳机制的维护方式,特意总结了一下,希望对朋友们有所帮助。

Socket应用:首先Socket 封装了tcp协议的,通过长连接的方式来与服务器通信,是由服务器和客户端两部分组成的,当客户端成功连接之后,服务器会记录这个用户,并为它分配资源,当客户端断开连接后,服务器会自动释放资源。

但在实际的网络环境中会有很多因素的导致服务器不知道客户端断开,或者客户端不知道服务器宕机,等等,比如网络中使用了路由器、交换机等等;这就带来一个问题:此时此刻服务器如何知道能否同客户端正常通信?解决这个问题的办法就是采用心跳。简单的说就是:在客户端和服务器连接成功后,隔一段时间服务器询问一下客户端是否还在,客户端收到后应答服务器"我还在",如果服务器超出一定时间(一般40-50秒)未收到客户端的应答,就判定它已经无法通信了,这时候需要释放资源,断开这个客户端用户。

客户端JS代码:

WebSocket协议的客户端程序

连接到WS服务器

向WS服务器发消息并接收消息

断开与WS服务器的连接

var wsClient=null;

var lastHealthTime = ; //记录最近一次心跳更新时间

var heartbeatTimer = null;//心跳执行timer

var checkTime = ; //心跳检查时间间隔-毫秒 10秒

var healthTimeOut = ;//心跳时间间隔-毫秒 20秒

var reconnectTimer = null;//重连接timer

var reconnectTime = ;//重连接时间10秒后

var uid = "";

var connectStatus = ; //状态

function connect(){

if (connectStatus == ){

wsClient=new WebSocket('ws://127.0.0.1:8000'); //这个端口号和容器监听的端口号一致

console.log("连接中...");

console.log("readyState:"+wsClient.readyState);

if (reconnectTimer){

clearTimeout(reconnectTimer);

}

//连接成功

wsClient.onopen = function(){

connectStatus = wsClient.readyState;

// 表名自己是uid1

var data = uid; //1标识连接

wsClient.send(data);

console.log('ws客户端已经成功连接到服务器上');

msg.innerHTML="连接成功...";

console.log("readyState:"+wsClient.readyState);

var time = new Date();

lastHealthTime = time.getTime();

if(heartbeatTimer){

clearInterval(heartbeatTimer);

}

heartbeatTimer = setInterval(function(){keepalive(wsClient)}, checkTime);

};

//收到消息

wsClient.onmessage = function(e){

console.log('ws客户端收到一个服务器消息:'+e.data);

console.log("readyState:"+wsClient.readyState);

val.innerHTML=e.data;

var data = e.data;

if (data){

var msg_type = data.substr(,);

var uid = data.substr();var time = new Date();

lastHealthTime = time.getTime();//更新客户端的最后一次心跳时间

}

}

//错误

wsClient.onerror = function(e){

connectStatus = wsClient.readyState;

console.log("error");

console.log("readyState:"+wsClient.readyState);

msg.innerHTML="连接错误...";

};

//关闭

wsClient.onclose = function(){

connectStatus = wsClient.readyState;

console.log('到服务器的连接已经断开');

msg.innerHTML="连接断开...";

console.log("readyState:"+wsClient.readyState);

//n秒后重连接

reconnectTimer = setTimeout(function(){

connect();

},reconnectTime);

}

}

}

btConnect.onclick = function(){

connect();

}

btSendAndReceive.onclick = function(){

wsClient.send('Hello Server');

}

btClose.onclick = function(){

console.log("断开连接");

console.log(wsClient.readyState);

wsClient.close();

}

function keepalive(ws){

var time = new Date();

console.log(time.getTime()-lastHealthTime);

if ((time.getTime()-lastHealthTime)>healthTimeOut){

msg.innerHTML="心跳超时,请连接断开...";

if (heartbeatTimer){

clearInterval(heartbeatTimer);

//n秒后重连接

ws.close();

reconnectTimer = setTimeout(function(){

connect();

},reconnectTime);

}

}

else{

msg.innerHTML="我依然在连接状态";

ws.send(data);

}

}

服务端代码:

这里我采用的是PHP语言,使用workman来实现的socket服务器端

require_once __DIR__ .'/Autoloader.php';

use Workerman\Worker;

use Workerman\Lib\Timer;

define('HEARTBEAT_TIME', 40);//心跳间隔时间

define('CHECK_HEARTBEAT_TIME', 10); // 检查连接的间隔时间

// 初始化一个worker容器,监听1234端口

$worker = new Worker('websocket://0.0.0.0:8000');

// 这里进程数必须设置为1

$worker->count = 1;

// worker进程启动后建立一个内部通讯端口

$worker->onWorkerStart = function($worker)

{

Timer::add(CHECK_HEARTBEAT_TIME, function()use($worker){

$time_now = time();

foreach($worker->connections as $connection) {

// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间

if (empty($connection->lastMessageTime)) {

$connection->lastMessageTime = $time_now;

continue;

}

// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接

if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {

$connection->close();

}

}

});

};

// 新增加一个属性,用来保存uid到connection的映射

$worker->uidConnections = array();

// 当有客户端发来消息时执行的回调函数

$worker->onMessage = function($connection, $data)use($worker)

{

$uid = $data; //uid

//echo 'connection...'.$uid.'\n';

// 判断当前客户端是否已经验证,既是否设置了uid

if(!isset($connection->uid))

{

if (intval($msg_type) === 1){ //连接

//上次收到的心跳消息时间

$connection->lastMessageTime = time();

// 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)

$connection->uid = $uid;

/* 保存uid到connection的映射,这样可以方便的通过uid查找connection,

* 实现针对特定uid推送数据

*/

$worker->uidConnections[$connection->uid] = $connection;

echo 'MSG USER COUNT:'.count($worker->uidConnections);

echo '\n';

return;

}

}

else{

if ($connection->uid === $uid){

//服务器收到心跳

//echo 'U-heart:'.$connection->uid.'\n';

$connection->lastMessageTime = time();

echo 'back send:';

$buffer = $uid;

$ret = sendMessageByUid($uid, $buffer);

$result = $ret ? 'ok' : 'fail';

// echo $result;

}

}

};

// 当有客户端连接断开时

$worker->onClose = function($connection)use($worker)

{

global $worker;

if(isset($connection->uid))

{

// 连接断开时删除映射

unset($worker->uidConnections[$connection->uid]);

echo 'CLOSE USER COUNT:'.count($worker->uidConnections);

echo '-'.$connection->uid.' closed';

echo '\n';

}

};

// 向所有验证的用户推送数据

function broadcast($message)

{

global $worker;

foreach($worker->uidConnections as $connection)

{

$connection->send($message);

}

}

// 针对uid推送数据

function sendMessageByUid($uid, $message)

{

global $worker;

if(isset($worker->uidConnections[$uid]))

{

$connection = $worker->uidConnections[$uid];

$connection->send($message);

return true;

}

return false;

}

// 运行所有的worker(其实当前只定义了一个)

Worker::runAll();

一个Socket连接管理池(心跳机制)

一个Socket连接管理池(心跳机制) http://cuisuqiang.iteye.com/blog/1489661

socket心跳包机制实践与理解

实现Socket心跳包主要分为两大类,第一采用tcp自带的KeepAlive,第二是自定义心跳包,恰巧我在产品VICA中都使用过,下面就这两种心跳包机制谈谈个人的理解与感受. 首先第一种KeepAli ...

zookeeper心跳机制流程梳理

zookeeper心跳机制流程梳理 Processor链Chain protected void setupRequestProcessors() { RequestProcessor finalPr ...

ESFramework 开发手册(07) -- 掉线与心跳机制(转)

虽然我们前面已经介绍完了ESFramework开发所需掌握的各种基础设施,但是还不够.想要更好地利用ESFramework这一利器,有些背景知识是我们必须要理解的.就像本文介绍的心跳机制,在严峻的In ...

判定生死的心跳机制 --ESFramework 4.0 快速上手(07)

在Internet上采用TCP进行通信的系统,都会遇到一个令人头疼的问题,就是"掉线".而"TCP掉线"这个问题远比我们通常所能想象的要复杂的多 -- 网络拓扑 ...

转 互联网推送服务原理:长连接+心跳机制(MQTT协议)

http://blog.csdn.net/zhangzeyuaaa/article/details/39028369 目录(?)[-] 无线移动网络的特点 android系统的推送和IOS的推送有什么 ...

Java: server/client 心跳机制实现 示例

心跳机制 心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制. 大部分CS的应用需要心跳机制.心跳机制一般在Server和Client都要实现,两者实现原理 ...

连接管理 与 Netty 心跳机制

一.前言 踏踏实实,动手去做,talk is cheap, show me the code.先介绍下基础知识,然后做个心跳机制的Demo. 二.连接 长连接:在整个通讯过程,客户端和服务端只用一个S ...

基于netty实现的长连接,心跳机制及重连机制

技术:maven3.0.5 + netty4.1.33 + jdk1.8   概述 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

随机推荐

ereg/eregi报错处理办法

ereg()函数和eregi()函数用法相同,不同之处在与ereg()区分大小写,eregi()不区分大小写 在php5.3以上的版本将不再支持eregi()和ereg()函数 处理办法: 正则函数处 ...

Janus WinForms Controls

http://blog.sina.com.cn/s/blog_68eb92020101kpw8.html

linux源代码阅读笔记 linux文件系统(转)

linux文件系统:   操作系统的文件数据除了文件实际内容外,还有非常多的属性,如文件权限(rwx)与文件属性(所有者.群组.时间参数等).   文件系统通常将这两部分数据存放在不同的块.权限属性放 ...

Python自动化运维之23、Dom

文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.最为关心的是,DOM把网页 ...

GlusterFS无法启动原因及处理方案

启动结果: Redirecting to /bin/systemctl status  glusterd.serviceglusterd.service - GlusterFS, a clustere ...

oracle 数据库删除表或表数据恢复问题

oracle恢复误删除的数据:使用闪回,ORACLE 10G及以上版本! 1. flashback table table_name to timestamp systimestamp-1; (sys ...

JQuery EasyUI Layout 在from布局自适应窗口大小

在JQuery EasyUI中,如果直接在form上布局时当窗口大小调整布局不会改变,将布局应用于body时中间隔着一个form,横竖不好弄. 网上有多个解决方案,一般都是写代码,在窗口大小改变时设置 ...

调整Windows XP 输入法顺序

執行 Regedit.exe 至 HKEY_CURRENT_USER\Keyboard Layout\Preload 調整輸入法順序,右邊欄中名稱為 1 的鍵值就是內定的輸入法,其值一般為 00000 ...

在eclipse中import java web项目时遇到的一些问题并将该项目通过tomcat发布

1.首先是import一个新的项目,会将已有的项目import到working space中,注意,你现在的项目路径就在working space了,而不是已有的项目路径! 2.点击eclipse上面 ...

35. CentOS-6.3安装Mysql-5.5.29

安装方式分为rpm和源码编译安装两种,本文是采用mysql源码编译方式,编译器使用Cmake.软件需要mysql-5.5.29.tar.gz和cmake-2.8.10.2.tar.gz,请自行下载.下 ...

php 如何实现心跳包,Socket心跳机制-JS+PHP实现相关推荐

  1. Android心跳包(一)——心跳机制

    转自:http://blog.csdn.net/rabbit_in_android/article/details/50119809 在写之前,我们首先了解一下为什么android维护长连接需要心跳机 ...

  2. C语言socket重连和心跳,c# socket 心跳 重连

    /// /// 检查一个Socket是否可连接 /// /// /// private bool IsConnected(Socket socket) { if (socket == null || ...

  3. php websocket 心跳包,websocket 心跳包重连

    上次我们讲过了websocket断线重连的问题,那么久会有人提出疑问了,心跳包重连跟断线重连有什么区别呢? 其实这两个都是为了达到一个目的,那就是保证当前设备的网络状态保持通畅...而断线重连呢,只能 ...

  4. Socket连接心跳包的机制总结

    文章目录 Socket连接心跳包的机制总结 心跳包的由来 心跳包的作用 心跳包由服务端还是客户端发送? Socket连接心跳包的机制总结 心跳包的由来 心跳包之所以叫心跳包是因为:它像心跳一样每隔固定 ...

  5. Socket心跳包机制总结

         跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着.事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包 ...

  6. java udp心跳机制,Socket心跳包机制总结

    跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着.事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一 ...

  7. Socket网络编程tcp聊天案例(心跳包,多线程,断线重连机制)

    实现一个聊天的案例,使用多线程和心跳包.当服务器断开的时候,客户端会自动尝试重新连接,当服务器开启的时候,客户端会自动连接 Server服务器类 package Demo3_Chat;import c ...

  8. 心跳检测以及应用层心跳包机制设计

    博主联系方式: QQ:1540984562 微信:wxid_nz49532kbh9u22 QQ交流群:892023501(嵌入式方向) QQ交流群:856398158(后端方向) 目录 心跳检测应用场 ...

  9. Android Socket连接(模拟心跳包,断线重连,发送数据等)

    首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 招聘 ITeye CSTO 写博客 发Chat 喻志强的博客 耐心 细心 用心 传播正能量 RSS订阅 原 A ...

最新文章

  1. java 区块链使用_使用Java创建第一个区块链
  2. 冒泡排序--通过冒泡算法让数组中最大的值成为数组中最后一个值
  3. 南方科技大学计算机交换生,国际合作 – 合作交流分类 – 南方科技大学生物医学工程系...
  4. 互联网基建成果,快速实现一个clubhouse要多久
  5. ui测试怎么做?依据文档有哪些_微信小程序开发流程有哪些?各个环节注意事项...
  6. Java笔记-JNI中简单的参数与返回值处理
  7. Shiro系列-Authenticator和AuthenticationStrategy是什么
  8. docker修改镜像的存储位置_win10家庭版Docker环境搭建步骤
  9. VS2010编译log4cpp日志库
  10. uniAPP上架iOS商店踩到的坑(记录)
  11. Swift版百思不得姐
  12. 潦草手写体也能轻松识别,快速提取文字不用愁
  13. 什么是正向代理,开放的代理软件使用
  14. DC入门(一)综合基础
  15. A Game of Thrones(39)
  16. 设计模式之命令模式(C语言)
  17. react input Onchange事件不能立刻拿到值,只能拿到上次输入的值
  18. 现代企业管理笔记——企业概论
  19. 火车头采集器向dedecms发布文章,使阅读权限为待审核稿件
  20. 简单dp-bone collector

热门文章

  1. 沈阳市房地产市场信息系统数据容灾与异地备份
  2. 这篇文章终于把中美德三国的工业互联网讲清楚了
  3. 相机标定篇——相机标定
  4. Mongo客户端【Studio 3T】免费激活方式
  5. java web 开发问题总结 1 原创-胡志广
  6. ExifTool常用使用方法
  7. 购买阿里云服务器搭建网站或个人博客详细教程
  8. springboot+uniapp实现简单注册登录
  9. IPD的决策评审DCP(1):概念、战略性
  10. Elastic 与 AWS 和解、英伟达收购 ARM 失败、英特尔加入RISC-V 组织|开源月报 Vol. 03...