现在都搞升级,本人也也使用JDK6进行开发。在开发工程中对Socket进行管理时对于这个连接的超时和是否失效进行研究。结果网上的资料很是让人失望,可以说google和百度下来,前几页原创很少都是抄袭。
说正经的,对于连接超时和失效肯定会想到设置超时时间和判断连接是否可用。但是设置超时时间后起作用是在调用read方法的时候,如果只是设置了超时时间却没有调用read,那么就算服务端中断连接,客户端也是无法得知的。而且就算read异常,当前的连接仍然是有效的。
我们来看如下代码运行后再继续:
服务端:
package com.service; import java.net.*; /** * @说明 从这里启动一个服务端监听某个端口 * @author 崔素强 */ public class DstService { public static void main(String[] args) { try { // 启动监听端口 8001 ServerSocket ss = new ServerSocket(8001); // 没有连接这个方法就一直堵塞 Socket s = ss.accept(); // 将请求指定一个线程去执行 new Thread(new DstServiceImpl(s)).start(); } catch (Exception e) { e.printStackTrace(); } } }
然后我们来看执行类,执行类在收到连接5秒后中断连接:
package com.service; import java.net.Socket; /** * @说明 服务的具体执行类 * @author 崔素强 */ 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 > 5) { socket.close(); System.out.println("服务端已经将连接关闭!"); break; } index++; Thread.sleep(1 * 1000); } } catch (Exception e) { e.printStackTrace(); } } }
我们在写一个客户端进行实验:
package com.client; import java.net.*; /** * @说明 服务的客户端,会请求连接并实时打印连接对象的一些信息,但是不会进行流的操作 * @author 崔素强 */ public class DstClient { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 8001); 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 ------------------------
从连接对象的属性信息来看,连接似乎没有中断。但实际虽然内存对象可用,但是物理连接已经失效。所以和网上其他抄袭来抄袭去的说法一样,靠连接对象属性来判断连接的可用性是不可行的。
大家会说那就判断调用read方法是否报错呗。我之前有文章已经讨论了关于调用网络里面流的一些内容,在没有判断这个流可用之前,我们是不会调用read方法的,当然具体你是怎么做的我不知道我在说我的情况!
读取网络数据流时的那个方法是这样的:
public static byte[] inputStreamToByte(InputStream inStream) throws Exception { int count = 0; int haveCheck = 0; // 如果在网络传输中数据没有完全传递,则方法返回0 while (count == 0) { count = inStream.available(); haveCheck++; if (haveCheck >= 50) return null; } byte[] b = new byte[count]; inStream.read(b); return b; }
就是说我们不会直接调用read方法,而available方法在流没有完整和网络中断时都会返回0,不会报错。
就是说就算你设置超时时间设置保持连接这些东西,只要你没有调用read的机会,你的程序就不会出问题。当然如果程序一直不调用read方法,那这个程序可真的够扯淡的了。
其实只要在使用这个连接的时候判断这个连接的可用性就行了,不要等着什么超时。
判断连接可用虽然网上一大片,其实就是那么回事,手动发送心跳包。
socket.sendUrgentData(0xFF); // 发送心跳包
乳沟你的连接已经中断,那么这个方法就会报错。
至于什么是心跳包,直接上理论吧。
心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。 用来判断对方(设备,进程或其它网元)是否正常运行,采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经离线。用于检测TCP的异常断开。基本原因是服务器端不能有效的判断客户端是否在线,也就是说,服务器无法区分客户端是长时间在空闲,还是已经掉线的情况。所谓的心跳包就是客户端定时发送简单的信息给服务器端告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。 比如有些通信软件长时间不使用,要想知道它的状态是在线还是离线就需要心跳包,定时发包收包。发包方:可以是客户也可以是服务端,看哪边实现方便合理,一般是客户端。服务器也可以定时发心跳下去。一般来说,出于效率的考虑,是由客户端主动向服务器端发包,而不是服务器向客户端发。客户端每隔一段时间发一个包,使用TCP的,用send发,使用UDP的,用sendto发,服务器收到后,就知道当前客户端还处于“活着”的状态,否则,如果隔一定时间未收到这样的包,则服务器认为客户端已经断开,进行相应的客户端断开逻辑处理!
当然不能单纯理解心跳包就是往对方放松数据,因为心跳包是用于状态验证的,不是真实的数据。
我们来看如下例子,服务端不变:
package com.client; import java.net.*; /** * @说明 服务的客户端,会请求连接并实时打印连接对象的一些信息,但是不会进行流的操作 * @author 崔素强 */ public class DstClient { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 8001); socket.setKeepAlive(true); socket.setSoTimeout(10); while (true) { socket.sendUrgentData(0xFF); // 发送心跳包 System.out.println("目前是正常的!"); Thread.sleep(3 * 1000); } } catch (Exception e) { e.printStackTrace(); } } }
看到控制台的输出:
目前是正常的! 目前是正常的! java.net.SocketException: Invalid argument: send at java.net.PlainSocketImpl.socketSendUrgentData(Native Method) at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:550) at java.net.Socket.sendUrgentData(Socket.java:928) at com.client.DstClient.main(DstClient.java:14)
那就是说,只要你的服务端断了,调用方法就会出错!
至于我说的他不会作为可见的数据你可以更改服务端代码打印客户端内容,你会发现服务端不会将心跳包内容展示给你!
InputStream ips = socket.getInputStream(); byte[] bt = inputStreamToByte(ips); if(null != bt) System.out.println(new String(bt)); else System.out.println("Bt is null"); System.out.println("****************************");
bt会一直是Null。为什么?因为我说的是对的!
哥通过示例说问题,也许不对有纰漏,但是咱绝对不去Copy,因为咱已经看厌了Copy!
请您到ITEYE看我的原创:http://cuisuqiang.iteye.com
或支持我的个人博客,地址:http://www.javacui.com
相关推荐
下面来介绍判断非阻塞SOCKET是否已经断开的几种方法: 注意要区分不同操作系统分别进行测试, 包括WINDOWS, LINUX和UNIX会各有不同。 在WINDOWS下比较简单,可以使用FD_CLOSE事件判断SOCKET是否已经断开 view ...
* 链接的最大空闲时间,超时的链接将关闭丢弃,可避免空闲时链接自动失效问题 * 使用channel处理池中的链接,高效 何为通用? 连接池的实现不依赖具体的实例,而依赖某个接口,本文的连接池选用的是io.Closer接口,...
注意:加入游戏,断开连接这两个功能在执行时,是另开线程的,我故意让关闭按钮和拖曳客户端区域移动窗口功能失效,看上去像是程序当住了,其实没当住,因为此时拖曳标题栏还是能移动窗口,右键菜单也可以弹出,这个...
3.加入游戏,断开连接这两个功能在执行时,是另开线程的,我故意让关闭按钮和拖曳客户端区域移动窗口功能失效,看上去像是程序当住了,其实没当住,因为此时拖曳标题栏还是能移动窗口,右键菜单也可以弹出,这个“当...
(1) socket,即套接字。你使用任何的网络硬件接口,只要它能够支持TCP/IP的通讯协议。这样的硬件包括:以太网、快速以网。 (2)串行口 在PlusWell Cluster容错软件配置中, 你应当配置有一个串行口通信路径。串口...
主要是为了防止已失效的连接请求报文段突然又传到了B,因而报文错乱问题 假定A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放 以后的某个时间才到达B,本来这是一个早已...
# 当把table_open_cache设置为很大时,如果系统处理不了那么多文件描述符,那么就会出现客户端失效,连接不上 max_allowed_packet = 1000000000 # 接受的数据包大小;增加该变量的值十分安全,这是因为仅当需要时才...
我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。 项目中遇到javascript跨域问题,父页面和子页面要通信,并且父子页面跨域,怎么办? ...
77.5. 设置session失效的时间 89 77.6. 设置MIME响应类型 89 77.7. 设置tomcat的默认访问页面 89 77.8. 设置tomcat管理用户 89 77.9. 附录 90 78. websphere 90 79. 常见异常 90 79.1. nullpointerexception 90 79.2...
znode是否使用Ephemeral类型,在session结束时自动删除(如果服务提供者真的挂了,那客户端就不会在robin调用服务时,使用该失效的服务,就不会重复报错) ###客户端 ####反射 客户端通过注册框架XXService rpc = ...
本文介绍了vscode 远程调试python的方法,分享给大家,具有如下: 实验环境 远程服务器:京东云,1核2G,centos7.3 64bit 本地环境配置 安装vscode,实验用的版本是1.10.2 vscode配置python插件,实验用的python...
" " "支持多服务器群集部署、负载均衡、组件级的失效即时" " "恢复(Fail Over)。支持Web层的集群和EJB集群。应 " " "提供较大型系统集群应用案例。 " " "支持会话亲和。均衡负载策略支持简单轮转、加权轮转" " ...
在客户端与数据节点之间共享数据 3 管理 Datanode 结点的状态报告, 包括 Datanode 结点的健康状态报 告和其所在结点上数据块状态报告,以便能够及时处理失效的数据结 点。 NameNode 与 SecondaryNameNode 的区别与...
取节点值文本()”返回的文本会失效的BUG。 2. 修改高级表格支持库,解决在鼠标按下和抬起之间收到时钟周期事件的情况下,无法收到“被单击”事件的BUG。 3. 修改扩展界面支持库三,解决单击卷帘菜单后导致日期框不...
文件为doc版,可自行转成txt,在手机上看挺好的。 本资源来自网络,如有纰漏还请告知,如觉得还不错,请留言告知后来人,谢谢!!!!! ...入门学习Linux常用必会60个命令实例详解 ...Linux提供了大量的命令,利用它...