java udp心跳机制,Socket心跳包机制总结
跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。
总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。
心跳检测步骤:
1 客户端每隔一个时间间隔发生一个探测包给服务器
2 客户端发包时启动一个超时定时器
3 服务器端接收到检测包,应该回应一个包
4 如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5 如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了
很多人会用boolean socketFlag = socket.isConnected() && socket.isClosed()来判断就行了,但事实上这些方法都是访问socket在内存驻留的状态,当socket和服务器端建立链接后,即使socket链接断掉了,调用上面的方法返回的仍然是链接时的状态,而不是socket的实时链接状态,所以这样心跳用这个不靠谱,下面给出例子证明这一点。
服务器端:
package com.csc.server;
import java.net.*;
/**
* @description 从这里启动一个服务端监听某个端口
* @author csc
*/
public class DstService {
public static void main(String[] args) {
try {
// 启动监听端口 30000
ServerSocket ss = new ServerSocket(30000);
// 没有连接这个方法就一直堵塞
Socket s = ss.accept();
// 将请求指定一个线程去执行
new Thread(new DstServiceImpl(s)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里我设置了启动新线程来管理建立的每一个socket链接,此处我们设置收到链接后10秒端来链接,代码如下:
package com.csc.server;
import java.net.Socket;
/**
* @description 服务的启动的线程类
* @author csc
*/
public class DstServiceImpl implements Runnable {
Socket socket = null;
public DstServiceImpl(Socket s) {
this.socket = s;
}
public void run() {
try {
int index = 1;
while (true) {
// 5秒后中断连接
if (index > 10) {
socket.close();
System.out.println("服务端已经关闭链接!");
break;
}
index++;
Thread.sleep(1 * 1000);//程序睡眠1秒钟
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上是服务端代码,下面写一个客户端代码来测试:
package com.csc.client;
import java.net.*;
/**
* @description 客户端打印链接状态
* @author csc
*/
public class DstClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 30000);
socket.setKeepAlive(true);
socket.setSoTimeout(10);
while (true) {
System.out.println(socket.isBound());
System.out.println(socket.isClosed());
System.out.println(socket.isConnected());
System.out.println(socket.isInputShutdown());
System.out.println(socket.isOutputShutdown());
System.out.println("------------我是分割线------------");
Thread.sleep(3 * 1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
先运行服务端代码,再运行客户端代码,我们会在客户端代码的控制台看到如下信息:
true
false
true
false
false
------------我是分割线------------
从连接对象的属性信息来看,连接是没有中断,但实际链接已经在服务端建立链接10秒后断开了。这说明了上述几个方法是不能实时判断出socket的链接状态,只是socket驻留在内存的状态。其实,此时如果调用流去读取信息的话,就会出现异常。
其实,想要判断socket是否仍是链接状态,只要发一个心跳包就行了,如下一句代码:
socket.sendUrgentData(0xFF); // 发送心跳包
关于心跳包的理论可以去google一下,我给出点参考:心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。 用来判断对方(设备,进程或其它网元)是否正常运行,采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经离线。用于检测TCP的异常断开。基本原因是服务器端不能有效的判断客户端是否在线,也就是说,服务器无法区分客户端是长时间在空闲,还是已经掉线的情况。所谓的心跳包就是客户端定时发送简单的信息给服务器端告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。 比如有些通信软件长时间不使用,要想知道它的状态是在线还是离线就需要心跳包,定时发包收包。发包方:可以是客户也可以是服务端,看哪边实现方便合理,一般是客户端。服务器也可以定时发心跳下去。一般来说,出于效率的考虑,是由客户端主动向服务器端发包,而不是服务器向客户端发。客户端每隔一段时间发一个包,使用TCP的,用send发,使用UDP的,用sendto发,服务器收到后,就知道当前客户端还处于“活着”的状态,否则,如果隔一定时间未收到这样的包,则服务器认为客户端已经断开,进行相应的客户端断开逻辑处理!
既然找到了方法,我们就在测试一下,服务端代码无需改动,客户端代码如下:
package com.csc.client;
import java.net.*;
/**
* @description 客户端打印链接状态
* @author csc
*/
public class DstClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 30000);
socket.setKeepAlive(true);
socket.setSoTimeout(10);
while (true) {
socket.sendUrgentData(0xFF); // 发送心跳包
System.out.println("目前处于链接状态!");
Thread.sleep(3 * 1000);//线程睡眠3秒
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
20130508162015307.jpeg
服务端程序运行10秒后再当执行“socket.sendUrgentData(0xFF);”语句时,socket链接断开了,所以会抛出异常。
另外注意,心跳包只是用来检测socket的链接状态,并不会作为socket链接的通信内容,这点应当注意。
java udp心跳机制,Socket心跳包机制总结相关推荐
- C语言socket重连和心跳,c# socket 心跳 重连
/// /// 检查一个Socket是否可连接 /// /// /// private bool IsConnected(Socket socket) { if (socket == null || ...
- 【计算机网络作业】Java UDP聊天 和 Socket编写一个简单的Web服务器
1-1 假设Tom和Jerry利用Java UDP进行聊天,请为他们编写程序.具体如下: (1).Tom和Jerry聊天的双方都应该具有发送端和接收端: (2).利用DatagramSocket与Da ...
- Java基础以及变量和运算符、包机制、javadoc生成
Java基础以及变量和运算符.包机制.javadoc生成 注释.标识符.关键字 注释 标识符 关键字 标识符注意点 数据类型 强类型语言 弱类型语言 Java的数据类型 基本类型(primitive ...
- 如何生成Doc说明文档及包机制
包机制 package basic;//这个是类文件所在包声明,必须要在第一行 //包的本质其实就是文件夹,方便区分,并且不同的包里可以出现同名的文件 import basic.Demo01;//这里 ...
- 【Java 网络编程】客户端 Socket 配置 ( 超时时间 | 端口复用 | Nagle 算法 | 心跳包机制 | 连接关闭机制 | 缓冲区大小 | 性能权重设置 | 紧急数据设置 )
文章目录 I 设置读取超时时间 II Socket 复用绑定端口设置 III 开启 Nagle 算法 ( 沾包 ) IV 心跳包机制 V 连接关闭处理 VI Socket 紧急数据内敛设置 VII S ...
- java udp心跳机制_心跳包机制整理汇总
[背景] 现需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要"互相"知道彼此的连接状态.比如在某一时刻,服务器需要知道当前有多少个客户端正在和其通信:某一个 ...
- Socket心跳包机制总结
跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着.事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包 ...
- php 如何实现心跳包,Socket心跳机制-JS+PHP实现
本文是我在实际工作中用到的Socket通信,关于心跳机制的维护方式,特意总结了一下,希望对朋友们有所帮助. Socket应用:首先Socket 封装了tcp协议的,通过长连接的方式来与服务器通信,是由 ...
- socket心跳机制图片_socket心跳包机制
心跳包 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包 心跳包的作用 网络中的接收和发送数据都是使用SOCKET进行实现.但 ...
最新文章
- git 添加外部项目地址
- 界面 高炉系统_浅议工业互联网与传统计算机系统的关系
- [Medical Image Processing] 2. Image Binary -【OTSU Algorithm Entropy Method】
- 对struts一点理解总结
- POJ 3984 迷宫问题
- Python学习笔记:动态添加与删除属性与方法
- 给Eclipse安装MinGW
- LinkedHashMap入门
- 大连理工大学c语言大作业,大连理工大学c语言大作业报告.docx
- phpdesigner 8 注册码
- JSP Commons-FileUpload 组件实现文件上传
- R语言—数据的调整与处理
- STM32串口中断接收一帧数据
- 给社交软件“一星保护”:95后在想什么
- 搜狗老域名作用之快速大量搜狗收录
- 电子科技大学计算机导师李珂,电院人物访谈录六——优秀学生李珂
- 小程序uniapp实现左滑删除效果
- Codeforces Round #548 (Div. 2), problem: (C) Edgy Trees 【并查集+快速幂】
- 支持生僻字且自动识别utf-8编码的php汉字转拼音类,支持生僻字且自动识别utf-8编码的php汉字转拼音类_php技巧...
- vue调用电脑端摄像头实时拍照
热门文章
- js图片轮播(翻页切换)
- python汇率编程_python – 确定汇率的算法
- 固定值的字段该不该建立索引
- 用imu_tk和imu_utils标定imu
- 算法 | 时间复杂度master 公式
- [SAP]MM模块术语
- dnf登录游戏自动连接服务器,游戏登录-新手引导-地下城与勇士官方网站-腾讯游戏...
- 《黑客防线》2010合订本(下半年)
- 5G NR标准: 第20章 5G的演进
- H5+CSS3 实现div垂直水平居中的几种方式