java socket 判断Socket连接失效
要判断socket连接链路是否可用时,不能通过socket.isClosed() 和 socket.isConnected() 方法判断,要通过心跳包 socket.sendUrgentData(0xFF) 。
当第一次连接成功后, socket.isClosed() ==false, socket.isConnected()==true,只有在自己端代码中显示调用socket.close()方法时,socket.isClosed() ==true。
而链路的不可用时,自己端的socket是不知道的,仍然是 socket.isClosed() ==false, socket.isConnected()==true。
要通过心跳包 socket.sendUrgentData(0xFF) 进行测验。
我们来看如下代码运行后再继续:
服务端:
- 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("****************************");
java socket 判断Socket连接失效的更多相关文章
- c#通过socket判断服务器连接是否正常
判断Socket是否连接上,需要通过发包来确认. 之前确认都是调用调用socket的connected属性,然而该属性是上次的连接是否成功的结果,不及时. // 检查一个Socket是否可连接 pri ...
- 如何判断Socket连接失效
http://cuisuqiang.iteye.com/blog/1453632 ——————————————————————————————————————————————————————————— ...
- JAVA 判断Socket 远程端是否断开连接
最近在做项目的时候,遇到这样一个问题,如何判断 Socket 远程端连接是否关闭,如果关闭的话,就要重建连接Socket的类提供了一些已经封装好的方法, 如 isClosed().isConnect ...
- Java中使用Socket连接判断Inputstream结束,java tcp socket服务端,python tcp socket客户端
最近在试着用java写一个socket的服务器,用python写一个socket的客户端来完成二者之间的通信,但是发现存在一个问题,服务器方面就卡在读取inputsream的地方不动了,导致后面的代码 ...
- JAVA网络编程Socket常见问题 【长连接专题】
一. 网络程序运行过程中的常见异常及处理 第1个异常是 java.net.BindException:Address already in use: JVM_Bind. 该异常发生在服务器端进行new ...
- 怎样实时判断socket连接状态?
对端正常close socket,或者进程退出(正常退出或崩溃),对端系统正常关闭 这种情况下,协议栈会走正常的关闭状态转移,使用epoll的话,一般要判断如下几个情况 处理可读事件时,在循环read ...
- C#socket通信时,怎样判断socket双方是否断开连接
我在Server端new了一个socket,然后bind,开了一个线程来accept前来连接的client,每接到一个client前来连接就新开一个线程和它进行通信.我把Server端得到的socke ...
- 【Java】简易Socket连接实现
客户端: import java.io.*; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.D ...
- java网络编程socket解析
转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...
随机推荐
- C++入门(1)
#include<>直接从编译器自带的函数库中寻找文件 #include""是先从自定义的文件中找 ,如果找不到在从函数库中寻找文件 采用"< > ...
- Linux系统性能调优之性能分析
1.Linux性能分析的目的1)找出系统性能瓶颈(包括硬件瓶颈和软件瓶颈):2)提供性能优化的方案(升级硬件?改进系统系统结构?):3)达到合理的硬件和软件配置:4)使系统资源使用达到最大的平衡.(一 ...
- 安装odoo过程中出现的问题
一 centos6.5 1. simplejson error:module not found fix: easy_install simplejson 2. python version erro ...
- zzUbuntu安装配置Qt环境
zz from http://blog.csdn.net/szstephenzhou/article/details/28407417 安装 QT4.8.6库+QT Creator 2.5.0 下载地 ...
- Bootstrap3的输入框数字点击修改效果
<div class="container"><div class="page-header"><h3>Bootstrap ...
- express+mongodb+mongoose增删改查
增加 修改 删除 数据库 这是一个前后端分离的项目前端项目地址:https://gitee.com/dingshao/express_qd.git后端项目地址:https://gitee.com/di ...
- $digest / $apply digest in progress报错
有的时候出于某种原因,如jq操作了model.或者$watch.setTimeout等函数改变了model,导致最后没有脏数据检测.所以我没就手动调用了$apply( )等.但是第一次运行的时候ang ...
- spark[源码]-sparkContext详解[一]
spark简述 sparkContext在Spark应用程序的执行过程中起着主导作用,它负责与程序和spark集群进行交互,包括申请集群资源.创建RDD.accumulators及广播变量等.spar ...
- Linux 系统日志管理 rsyslogd配置文件
rsyslogd配置文件 rsyslogd 服务是依赖其配置文件 /etc/rsyslog.conf 来确定哪个服务的什么等级的日志信息会被记录在哪个位置的.也就是说,日志服务的配置文件中主要定义了 ...
- 20145314郑凯杰 《Java程序设计》第9周学习总结 积极主动敲代码
20145314郑凯杰 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 ①JDBC(Java DataBase Connectivity) 即java数据库连接,是一种用于 ...