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用法详解 在 ...
随机推荐
- python全栈开发从入门到放弃之模块和包
一 模块 1 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编 ...
- 杭电1020Encoding
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1020 题目: Problem Description Given a string containing ...
- win 7 64 安装 tensorflow
1:安装 python 3.5 2. 安装 pip 3: 安装 tensorflow 4,demo
- manager
S 识别 M 买账 A-安排 R-认同 T-提问识别上级的沟通特点,判断形势,识别沟通的时机摆正自己的角色位置,礼多人不怪,回应情绪做好沟通准备,有策略,安排合适时间听取反馈意见,认同并接纳指导提问 ...
- WebService发布协议--SOAP和REST的区别
HTTP是标准超文本传输协议.使用对参数进行编码并将参数作为键值对传递,还使用关联的请求语义.每个协议都包含一系列HTTP请求标头及其他一些信息,定义客户端向服务器请求哪些内容,服务器用一系列HTTP ...
- selenium实现excel文件数据的读、写
在进行软件测试或设计自动化测试框架时,一个不可避免的过程就是: 参数 化,在利用 python 进行自动化测试开发时,通常会使用 excel 来做数据管 理,利用 xlrd.xlwt 开源包来读写 e ...
- zookeeper和淘宝dubbo的关系
Dubbo建议使用Zookeeper作为服务的注册中心. 1. Zookeeper的作用: zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知 ...
- 20145303 实验一 Java开发环境的熟悉(Linux + Eclipse)
20145303 实验一 Java开发环境的熟悉(Linux + Eclipse) 实验题目(4):实现学生成绩管理功能,并进行测试 思路: 对于实现学生成绩管理(student performanc ...
- 20145313张雪纯 《Java程序设计》第6周学习总结
20145313张雪纯 <Java程序设计>第6周学习总结 教材学习内容总结 将数据从来源中取出,可以使用输入串流:将数据写入目的地,可以使用输出串流. 输入串流代表对象为java.io. ...
- LeetCode (262):Nim Game
You are playing the following Nim Game with your friend: There is a heap of stones on the table, eac ...