热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ServerSocket连接断开处理方式

ServerSocket连接断开处理方式1、概述:2、异常信息:2.1、之前有人给出的方案:3、代码分析4、场景分析4.1.建立Socke

ServerSocket连接断开处理方式

    • 1、概述:
    • 2、异常信息:
      • 2.1、之前有人给出的方案:
    • 3、代码分析
    • 4、场景分析
      • 4.1.建立Socket连接,底层就是TCP连接:
      • 4.2.发送数据
      • 4.3.断开连接
    • 5、总结:


1、概述:

WebSocket是一种在单个TCP连接上进行全双工通信的协议。在我们应用的过程仲,客户端会出现无故断开的情况。这里提供一种连接断开的异常检测机制。

2、异常信息:

系统中出现的异常
2019-03-12 18:56:24,044 ERROR [com.lenovo.SocketServer.ping(172)] -
2019-03-12 18:56:24,045 ERROR [com.lenovo.SocketServer.ping(173)] -

2.1、之前有人给出的方案:

总结产生原因,在服务端/客户端单方面关闭连接的情况下,另一方依然以为tcp连接仍然建立,试图读取对方的响应数据,导致出现Software caused connection abort: recv failed的异常。 通过inputstream的available()方法来判断,是否有响应结果。但是对SocketInputStream没有效果,因为SocketInputStream 在断开连接和数据正常传输状态的下 available 返回值都是0。

3、代码分析

其中InputStream 类型为 SocketInputStream,但是SocketInputStream 在 jdk 的rt.jar 中,是JDK的核心专用类型,不是public类型,只能通过反射获取其中的参数。 有一行代码:boolean eof = (Boolean) getValueByKey(inputStream, “eof”);获取eof 字段的值就是通过Java 的反射机制做的。下面会重点说这个字段。

开启WebSocket服务端:

private static void generateTCPServer() throws IOException{ServerSocket serverSocket = new ServerSocket(12345);while (true){Socket socket = serverSocket.accept();Thread thread = new Thread(){@Overridepublic void run(){System.out.println("开启新的线程"); while (true){try {if (socket == null){System.out.println("socket为null");Thread.interrupted();}else{boolean flag = handler(socket);if(!flag){System.out.println("Client Down");Thread.interrupted();break;}Thread.sleep(50);}}catch (Exception e){logger.error("System error");logger.error(e.getMessage());e.printStackTrace();}}}};thread.start();}}

连接数据处理逻辑:

public static boolean handler(Socket socket) {try {OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();// 接受客户端的响应byte[] b = new byte[51200];inputStream.read(b);// 第一种方式:通过获取eof 参数获取当前连接是否断开的参数boolean eof = (Boolean) getValueByKey(inputStream, "eof");if (true == eof) {// 已经断开logger.error("");return false;}// 第二种方式:获取传输的内容String msg = CommonUtil.toHexString(b);String head = msg.substring(0, 2);// client断开if (head.equals("00")) {logger.error("");return false;}} catch (IOException e) {logger.error("IOException by TCP");logger.error(e);}return true;}

4、场景分析


4.1.建立Socket连接,底层就是TCP连接:

连接过程代码走到 inputStream.read(b);就I/O中断了 并等待请求数据过来,继续执行下面的代码。new byte[51200] 为下一次请求建立了一缓存区,用于接收下一次请求的数据。
在这里插入图片描述
这里Thread的状态仍然是RUNNABLE。
在这里插入图片描述
发起连接请求:响应 为空

在这里插入图片描述
流程处理过程中部分核心参数:

OutputStreamappend:falsechannel:nullclosed:falseclosing:falsesocket:bound:truecreated:trueconnected:trueclosed:falseInputStreamchannel:nullclosed:false closing:falseeof:false =========== 不一样的地方socket:bound:truecreated:trueconnected:trueclosed:false

4.2.发送数据

代码从连接检测的代码处继续执行,一直到返回响应结束。
// 第一种方式:通过获取eof 参数获取当前连接是否断开的参数
boolean eof = (Boolean) getValueByKey(inputStream, “eof”);
在这里插入图片描述
在这里插入图片描述

流程处理过程中部分核心参数:如果连接没有断开,就是上一次请求结束后的参数。

OutputStreamappend:falsechannel:nullclosed:falseclosing:falsesocket:bound:truecreated:trueconnected:trueclosed:falseInputStreamchannel:nullclosed:false closing:falseeof:false =========== 不一样的地方socket:bound:truecreated:trueconnected:trueclosed:false

4.3.断开连接

代码从连接检测的代码处继续执行,但是在连接断开检测的时候就结束了 并返回false。
// 第一种方式:通过获取eof 参数获取当前连接是否断开的参数
boolean eof = (Boolean) getValueByKey(inputStream, “eof”);
以下两种方式中的任意一种都可以作为连接断开检测代码,推荐第一种:
在这里插入图片描述
在这里插入图片描述

流程处理过程中部分核心参数:连接断开后eof为true.

OutputStreamappend:falsechannel:nullclosed:falseclosing:falsesocket:bound:truecreated:trueconnected:trueclosed:falseInputStreamchannel:nullclosed:false closing:falseeof:true ============不一样的地方socket:bound:truecreated:trueconnected:trueclosed:false

5、总结:

优先通过连接状态来判断客户端是否断开。需要建立一种异常检测机制和连接重连的机制。


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
author-avatar
荒唐中带着正经_638
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有