Winform怎么做心跳?要具体代码,谢谢了啊!
解决方法:下面是客户端心跳包核心代码:# region ++++++++++++++++++++ 客户端的感觉系统 //启动记时器 public void BeginTheTimer() { //th_UserLogin(); //这里只是要一个object类型数据,用它做为下面Timer的参数之一,没有其它意思 object myobject = (object)7; //暂时设定为1秒钟启动一次! SystemThreadingTimer t = new SystemThreadingTimer (new SystemThreadingTimerCallback(testTheNet), myobject, 1000, 1000); } //启动监视"已登录用户通信情况"的线程 public void testTheNet(object myobject) { //UserPassport up=new UserPassport(); Thread sendMyPulseThPro = new Thread(new ThreadStart(delegateSendMyPulse)); sendMyPulseThProStart(); } /// <summary> /// 每隔1秒就是要来做这些事情的 /// </summary> public void delegateSendMyPulse() { loginServer lser = new loginServer(); Login l = new Login(); lId = lserMyLoginId; lClientTypeVersion = version; lRequestType = 3; //3是确认联接正常的一个信号(让服务知道它与服务器的联接是正常的) loginServer lserver = new loginServer(); //启动一个新线程去发送数据 Thread thSendDat2 = new Thread (new ParameterizedThreadStart(lserverdelgSendDataMethod)); thSendDat2Start(l); thSendDat2IsBackground = true; //标记我已经发送出去一次数据了 longinserverMyLostTime += 1; //如果外发了3次请求暗号后仍不见服务器的回应,则认为客户端已经与服务器断开联系了 if(longinserverMyLostTime>=3) { //停止Timer //告诉用户:“你已经与服务器失去联系了…………” longinserverControls["txtShowMsg"]Text = "You have lost the connect!"; } }# endregion +++++++++++++++++++++ 客户端的感觉系统下面是服务器端核心代码如下:# region +++++++++++++++++++++++ 服务器的感觉系统 //启动记时器 public void LoadTheTimer() { object o=(object)loginedCount++; UserPassport up = new UserPassport(); //暂时设定为1秒钟启动一次! SystemThreadingTimer t = new SystemThreadingTimer (new SystemThreadingTimerCallback(watchTheLoginUser), o, 1000, 1000); } //启动监视"已登录用户通信情况"的线程 public void watchTheLoginUser(object o) { //UserPassport up=new UserPassport(); Thread checktheloginuser = new Thread(new ThreadStart(iAmAWatcher)); checktheloginuserStart(); } //真正做事的工人:这个工人的使命是每隔1秒钟后就查看一下登记薄 //registry里面有谁没有定时来向服务器报到了,如果出现谁三次检查都没有签到则除之名 public void iAmAWatcher() { thistxtLoginText += "@+"; int index = 0; for (index = 0; index < loginedCount; index++) { if (myRegistry[index]alive==false&®istry[index]studentID!="") { lock(this) { //坏(未到)记录增加一次 myRegistry[index]no_check_in_count += 1; if (myRegistry[index]no_check_in_count >= 3) { //thislblShowMsgText = "the student" //thislblShowMsgText += registry[index]studentIDToString() //thislblShowMsgText += "is diaoxianle!"; thistxtLoginText += "88"; //标记该人已经与服务器失去连接了,因为他有连续3次的未到记录存在 registry[index]studentID = ""; registry[index]StudentName = ""; registry[index]StudentIP = ""; registry[index]status = 2; //掉线 } } } } } //定时检查在线人目前状态# endregion +++++++++++++++++++ 服务器的感觉系统 本文来自CSDN博客,转载请标明出处: http://blogcsdnnet/QGJava/archive/2010/07/19/5745776aspx
不知这个心跳包传输模式是广播还是点到点呢
也许是交换机工作模式不匹配你的应用,二级交换可直接广播,三级交换会过滤广播的心跳包需要三级交换配置下转发广播
检查几点,心跳包发包模式,网络互通,程序设置,交换机工作模式
消息推送(Push)就是通过服务器把内容主动发送到客户端的过程。运营人员通过自己的产品或第三方工具对用户移动设备进行主动消息推送。完成推送后,消息通知会展示在移动设备的锁定屏幕及通知栏上,用户点击通知即可去往相应页面。
现在流行的消息推送实现方式,主要为长链接方式实现。其原理是客户端主动和服务器建立TCP长链接,长链接建立之后,客户端定期向服务器发送心跳包用于保持链接,当有消息要发送的时候,服务器可以直接通过这个已经建立好的长链接,将消息发送到客户端。
个推作为国内移动推送领域的早期进入者,于2010年推出个推消息推送SDK产品,十余年来持续为移动开发者提供稳定、高效、智能的消息推送服务,成功服务了人民日报、新华社、CCTV、新浪微博等在内的数十万APP客户。个推消息推送,也是运用的长链接方式实现消息推送的,其长链接稳定性高、存活好,消息送达率高。开发者通过集成个推消息推送SDK,即可简单、快捷地实现Android和iOS平台的消息推送功能,有效提高产品活跃度、增加用户留存。
如果您对个推消息推送感兴趣,欢迎点击前往了解详情。
个推消息推送工作原理
踩着年末的尾巴,提前布局来年,为来年的工作做个好的铺垫,所以就开始了面试历程,因为项目中使用到了 WebSocket ,面试官在深挖项目经验的时候,也难免提到 WebSocket 相关的知识点,因为之前并没有考虑这么深,所以,回答的还是有所欠缺,因此,赶紧趁热再熟悉熟悉,也借此机会,整理出来供大家咀嚼,每个项目都有其值得挖掘的闪光点,要用有爱的眼睛去发现。
WebSocket 是一种在单个TCP连接上进行全双工通信的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行双向数据传输。(维基百科)
WebSocket 本质上一种计算机网络应用层的协议,用来弥补 http 协议在持久通信能力上的不足。
WebSocket 协议在2008年诞生,2011年成为国际标准。现在最新版本浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
WebSocket 的其他特点包括:
我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?
因为 HTTP 协议有一个缺陷:通信只能由客户端发起,不具备服务器推送能力。
举例来说,我们想了解查询今天的实时数据,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
在 WebSocket 协议出现以前,创建一个和服务端进双通道通信的 web 应用,需要依赖HTTP协议,进行不停的轮询,这会导致一些问题:
http 协议本身是没有持久通信能力的,但是我们在实际的应用中,是很需要这种能力的,所以,为了解决这些问题, WebSocket 协议由此而生,于2011年被IETF定为标准RFC6455,并被RFC7936所补充规范。并且在 HTML5 标准中增加了有关 WebSocket 协议的相关 api ,所以只要实现了 HTML5 标准的客户端,就可以与支持 WebSocket 协议的服务器进行全双工的持久通信了。
WebSocket 与 HTTP 的关系图:
下面一张图说明了 HTTP 与 WebSocket 的主要区别:
不同点:
与http协议一样, WebSocket 协议也需要通过已建立的TCP连接来传输数据。具体实现上是通过http协议建立通道,然后在此基础上用真正 WebSocket 协议进行通信,所以WebSocket协议和http协议是有一定的交叉关系的。首先, WebSocket 是一个持久化的协议,相对于 HTTP 这种非持久的协议来说。简单的举个例子吧,用目前应用比较广泛的 PHP 生命周期来解释。
HTTP 的生命周期通过 Request 来界定,也就是一个 Request 一个 Response ,那么在 HTTP10 中,这次 HTTP 请求就结束了。
在 HTTP11 中进行了改进,使得有一个 keep-alive,也就是说,在一个 HTTP 连接中,可以发送多个 Request,接收多个 Response。但是请记住 Request = Response, 在 HTTP 中永远是这样,也就是说一个 Request 只能有一个 Response。而且这个 Response 也是被动的,不能主动发起。首先 WebSocket 是基于 HTTP 协议的,或者说借用了 HTTP 协议来完成一部分握手。
首先我们来看个典型的 WebSocket 握手
熟悉 HTTP 的童鞋可能发现了,这段类似 HTTP 协议的握手请求中,多了这么几个东西。
这个就是 WebSocket 的核心了,告诉 Apache 、 Nginx 等服务器:注意啦,我发起的请求要用 WebSocket 协议,快点帮我找到对应的助理处理~而不是那个老土的 HTTP 。
这里开始就是 HTTP 最后负责的区域了,告诉客户,我已经成功切换协议啦~
依然是固定的,告诉客户端即将升级的是 WebSocket 协议,而不是 mozillasocket ,lurnarsocket 或者 shitsocket 。
然后, Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key 。服务器:好啦好啦,知道啦,给你看我的 ID CARD 来证明行了吧。后面的, Sec-WebSocket-Protocol 则是表示最终使用的协议。至此,HTTP 已经完成它所有工作了,接下来就是完全按照 WebSocket 协议进行了。总结, WebSocket 连接的过程是:
优点:
缺点:
心跳就是客户端定时的给服务端发送消息,证明客户端是在线的, 如果超过一定的时间没有发送则就是离线了。
当客户端第一次发送请求至服务端时会携带唯一标识、以及时间戳,服务端到db或者缓存去查询改请求的唯一标识,如果不存在就存入db或者缓存中, 第二次客户端定时再次发送请求依旧携带唯一标识、以及时间戳,服务端到db或者缓存去查询改请求的唯一标识,如果存在就把上次的时间戳拿取出来,使用当前时间戳减去上次的时间, 得出的毫秒秒数判断是否大于指定的时间,若小于的话就是在线,否则就是离线;
通过查阅资料了解到 nginx 代理的 websocket 转发,无消息连接会出现超时断开问题。网上资料提到解决方案两种,一种是修改nginx配置信息,第二种是 websocket 发送心跳包。下面就来总结一下本次项目实践中解决的 websocket 的断线 和 重连 这两个问题的解决方案。主动触发包括主动断开连接,客户端主动发送消息给后端
主动断开连接,根据需要使用,基本很少用到。
下面主要讲一下客户端也就是前端如何实现心跳包:
首先了解一下心跳包机制
跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在 TCP 的机制里面,本身是存在有心跳包的机制的,也就是 TCP 的选项: SO_KEEPALIVE 。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的 echo 包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
心跳检测步骤:
针对这种异常的中断解决方案就是处理重连,下面我们给出的重连方案是使用js库处理:引入 reconnecting-websocketminjs ,ws建立链接方法使用js库api方法:
断网监测支持使用js库: offlineminjs
以上方案,只是抛砖引玉,如果大家有更好的解决方案欢迎评论区分享交流。
WebSocket 是为了在 web 应用上进行双通道通信而产生的协议,相比于轮询HTTP请求的方式,WebSocket 有节省服务器资源,效率高等优点。WebSocket 中的掩码是为了防止早期版本中存在中间缓存污染攻击等问题而设置的,客户端向服务端发送数据需要掩码,服务端向客户端发送数据不需要掩码。WebSocket 中 Sec-WebSocket-Key 的生成算法是拼接服务端和客户端生成的字符串,进行SHA1哈希算法,再用base64编码。WebSocket 协议握手是依靠 HTTP 协议的,依靠于 HTTP 响应101进行协议升级转换。
1、服务器端运行一个常驻线程,用于实时检查在线列表中,是否存在超时用户,有的话,就做相应处理,并将用户从在线列表中删除
2、用户登陆成功后,在客户端用JavaScript,使用定时器,每间隔固定时间(比如20秒),通过Ajax异步发送请求服务器某个页面,或者WebService之类的接口。这就是所谓的心跳请求。
3、服务器收到用户的心跳请求后,更新用户最后一次联系服务器的时间。
这样服务器检查超时的时候,实际上就可以把当前时间,减去用户最后一次联系服务器的时间,如果超过一个指定值,比如1分钟,那就认为这个用户离线了。
PS:原理很简单,但要设计一个高效的机制,还是要多考虑实现的算法,特别是服务器端的在线列表,和检查超时的机制。我曾经在几年前做了一个实现,后来重写了N遍,才发现了一个相对比较合理的方法。
socketsetKeepAlive()应该写在客户端,serveraccept()是服务器端的。
心跳的也有现成的,不过依赖别的类。大概贴一下,就是这么个意思。
public class HBHBThread extends Thread {
private CommandDeal command;
/
@return the command
/
public CommandDeal getCommand() {
return command;
}
/
@param command
the command to set
/
public void setCommand(CommandDeal command) {
thiscommand = command;
}
public void run() {
long maxWait = SendConfighbhb_wait;
if (maxWait < 1000) {
maxWait = 1000;
}
Date lastTime;
long timeDiv=0;
while (1 == 1) {
lastTime=SocketQueueObjectgetLastContactTime();
if(lastTime!=null){
timeDiv=(new Date())getTime() - SocketQueueObjectgetLastContactTime()getTime();
Systemoutprintln("TimeDiv:"+timeDiv);
}
// 上次联系的时间超过最大等待,或者还没联系过
if (lastTime == null|| timeDiv >=maxWait) {
Systemoutprintln("HBHB");
commandsendHbhbCommand();
}else if(maxWait>timeDiv){
maxWait=maxWait-timeDiv;
}
try{
thissleep(maxWait);
}catch(Exception e){
eprintStackTrace();
}
}
}public class HBHBCommandDeal extends CommandDealInterface {
private static Logger msg_logger = LoggergetLogger("socketMsg");
@SuppressWarnings("unchecked")
public List doCommand(SocketQueueObject socketQueueObject, Map command) throws Exception {
List<String> commandList = (List) commandget(ConstantsSMSCOMMAND);
byte[] hbhbMsg = TL1ToolcreateCommand(commandListget(0));
msg_loggerinfo(" send message to sms packed:" + new String(hbhbMsg, "ISO-8859-1"));
TL1RetrunMessage retMsg = socketQueueObjectcommNGNServer(hbhbMsg);
retMsgresolve();
msg_loggerinfo(" recevice message from sms:"+ retMsggetMessage());
List returnList = new ArrayList();
returnListadd(retMsg);
return returnList;
}
}
你可以自己找找看啊。
心跳包,通常是客户端每隔一小段时间向服务器发送的一个数据包,通知服务器自己仍然在线,并传输一些可能有必要的数据。因按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。事实上为了保持长连接,至于包的内容,是没有特别规定的,不过一般都是很小的包,或者只是包含包头的一个空包。
在TCP协议的机制里面,本身是存在有心跳包机制的,也就是TCP协议中的SO_KEEPALIVE,系统默认是设置2小时的心跳频率。需要用要用setsockopt将SOL_SOCKETSO_KEEPALIVE设置为1才是打开,并且可以设置三个参数tcp_keepalive_time/tcp_keepalive_probes/tcp_keepalive_intvl,分别表示连接闲置多久开始发keepalive的ACK包、发几个ACK包不回复才当对方死了、两个ACK包之间间隔多长。
TCP协议会向对方发一个带有ACK标志的空数据包(KeepAlive探针),对方在收到ACK包以后,如果连接一切正常,应该回复一个ACK;如果连接出现错误了(例如对方重启了,连接状态丢失),则应当回复一个RST;如果对方没有回复,服务器每隔多少时间再发ACK,如果连续多个包都被无视了,说明连接被断开了。
“心跳检测包”是属于TCP协议底层的检测机制,上位机软件只是解析显示网口的有用数据包,收到心跳包报文属于TCP协议层的数据,一般软件不会将它直接在应用层显示出来,所以看不到。以太网中的“心跳包”可以通过“以太网抓包软件”分析TCP/IP协议层的数据流看到。报文名称”TCP Keep-Alive”。
一些比较可靠的以太网转串口模块,都有心跳包的检测,比如致远电子的ZNE-100TL模块,配置“心跳包检测”间隔时间设为“10”秒,使用一款”wireshark”的抓包软件来实际查看下TCP/IP协议层“心跳包”数据。
0条评论