当前位置: 首页 > news >正文

Java的Socket通信的断网重连的正确写法

Java的Socket通信的断网重连的正确写法

    • Socket通信的断网重连介绍
    • 客户端与服务端源码
    • 演示截图
      • 本地演示
      • 服务器演示
        • 演示截图
    • 总结

Socket通信的断网重连介绍

针对于已经建立通信的客户端与服务器,当客户端与服务器因为网络问题导致网络不通而断开连接了或者由于服务器端的服务被突然停掉,而客户端进行的一种尝试重新建立连接的操作;我采用的是Socket自带的往通道内写数据是否成功来判断当前连接是否断开,采用该方式的好处是简洁易懂,高效通用。

一般的采用ping命令,定时尝试重新建立新的连接的方式,都有一些不足之处,前者是没办法针对端口进行判断,效果不好;后者则是每次都建立新的连接,导致服务器端压力会较大,而且相对的代码逻辑也会更加复杂。而采用本文介绍的写数据的方式,即可简单判断连接是否断开;原理是当连接断开后,写数据时会报错,捕获该错误即可;底层原理则是Java的Socket底层代码,采用C语言或者C++编写,在那里肯定是去判断IP和端口是否可以访问到的逻辑;有需要的话,下篇文章可以查看源码,进一步熟悉Java的网络编程知识。

客户端与服务端源码

为了方便演示和理解,仅进行了服务端向客户端发送数据,客户端接收数据的单向通信方式;实际扩展也非常简单。可以由读者进行尝试实现,增加网络编程知识的熟练度。

服务端

package com;import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** @author BBYH*/
public class MyServerSocket {public static final Integer PORT = 8080;private static Socket myServerSocket;private static OutputStream outputStream;public static void listen() {System.out.println("服务端监听端口" + PORT);new Thread(() -> {try (ServerSocket serverSocket = new ServerSocket(PORT)) {while (true) {try {myServerSocket = serverSocket.accept();System.out.println("服务端接收到来自客户端的连接");outputStream = myServerSocket.getOutputStream();new Thread(() -> {Scanner scanner = new Scanner(System.in);while (true) {try {System.out.println("向客户端发送消息:");String sendContent = scanner.next();outputStream.write(sendContent.getBytes(StandardCharsets.UTF_8));} catch (Exception e) {e.printStackTrace();}}}).start();} catch (IOException e) {throw new RuntimeException(e);}}} catch (IOException e) {e.printStackTrace();}}).start();}public static void main(String[] args) {listen();}
}

客户端

package com;import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Date;/*** @author BBYH* @description 通过socket的写数据,来判断当前的socket是否连通*/
public class ClientSocket {public static final String IP = "127.0.0.1";public static final Integer PORT = 8080;private static Socket socket;private static InputStreamReader reader;private static OutputStream outputStream;public static void main(String[] args) {// 首次建立连接connect();}public static void connect() {System.out.println("向服务端端口" + PORT + "申请建立连接");try {socket = new Socket(IP, PORT);System.out.println("客户端与服务器端连接建立成功");reader = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);outputStream = socket.getOutputStream();// 开启读取线程openReadThread();} catch (Exception e) {e.printStackTrace();}}private static void openReadThread() {new Thread(() -> {// 开启断网重连线程new Thread(() -> {while (true) {if (isDisContentWithServer()) {while (true) {try {socket = new Socket(IP, PORT);reader = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);outputStream = socket.getOutputStream();System.out.println(new Date() + ":重新建立连接成功");break;} catch (IOException e) {System.out.println(new Date() + ":尝试重新建立连接失败");try {Thread.sleep(3000);} catch (InterruptedException ex) {throw new RuntimeException(ex);}}}}}}).start();char[] readBuf = new char[1024];while (true) {try {if (reader.ready()) {int read = reader.read(readBuf);System.out.println("接收到来自服务端的消息:" + new String(readBuf, 0, read));}} catch (Exception e) {e.printStackTrace();}}}).start();}public static boolean isDisContentWithServer() {try {outputStream.write(("发送数据").getBytes(StandardCharsets.UTF_8));Thread.sleep(3000);return false;} catch (Exception e) {return true;}}
}

尽管在客户端开启断网重连线程中进行了两次while循环,不是很优雅,但仍然可以较为清晰的理解到代码的执行逻辑;即,每隔固定时间(3秒)进行是否连通的判断,当发现不连通的,则进行尝试重连(重新建立连接),该处的逻辑没有办法省略,由于客户端一般不长时间运行,消耗的资源虽然较多,但在程序运行结束后也自然就释放了。

演示截图

演示流程为:开启服务器 – 客户端建立连接 – 服务器发送一些数据 – 服务器断开连接 – 客户端尝试重连(自动进行) – 重新开启服务器 – 服务器再次发送数据

在该过程中,服务器在首次开启后的关闭,即代表了客户端的断网,实际情况中可以采用服务器,然后采用断开Wifi的方式代替这个关闭服务器,只要保证了客户端与服务器无法连通,即代表断网了,后面的重连则可以采用再次打开Wifi,重新连接上网络,连接则自动建立好

本地演示

开启服务器 – 客户端建立连接 – 服务器发送一些数据
在这里插入图片描述

服务器断开连接 – 客户端尝试重连(自动进行)
在这里插入图片描述

重新开启服务器 – 服务器再次发送数据
在这里插入图片描述

服务器演示

采用的是我申请的阿里云服务器,流程与上述文字说明一致,采用断开Wifi的形式来代替服务器关闭的效果;服务器关闭同样被我测试过,与本地一样,可以进行重连。由于我采用Xshell进行连接,当断开连接后日志会失效,所以采用后台任务记录运行打印的日志;命令为 nohup java com.MyServerSocket > MyServerSocket.out &

关于不采用防火墙来演示断网效果,则是因为防火墙无法拦截已经建立好的Socket通道,经测试发现该现象,读者可手动进行验证,如有意外情况,可向我进行反馈。

由于nohup命令的输入重定向,我暂时还没研究明白,所以目前服务端也不进行发送数据,两边都只是简单的建立连接和断开,代码进行了简单的调整,如下:

服务器端

package com;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/*** @author BBYH*/
public class MyServerSocket {public static final Integer PORT = 8080;private static Socket myServerSocket;public static void listen() {System.out.println("服务端监听端口" + PORT);new Thread(() -> {try (ServerSocket serverSocket = new ServerSocket(PORT)) {while (true) {try {myServerSocket = serverSocket.accept();System.out.println("服务端接收到来自客户端的连接");} catch (IOException e) {throw new RuntimeException(e);}}} catch (IOException e) {e.printStackTrace();}}).start();}public static void main(String[] args) {listen();}
}

客户端

package com;import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Date;/*** @author BBYH* @description 通过socket的写数据,来判断当前的socket是否连通*/
public class ClientSocket {public static final String IP = "127.0.0.1";public static final Integer PORT = 8080;private static Socket socket;private static OutputStream outputStream;public static void main(String[] args) {// 首次建立连接connect();}public static void connect() {System.out.println("向服务端端口" + PORT + "申请建立连接");try {socket = new Socket(IP, PORT);System.out.println("客户端与服务器端连接建立成功");outputStream = socket.getOutputStream();// 开启断网重连线程openReConnectThread();} catch (Exception e) {e.printStackTrace();}}private static void openReConnectThread() {new Thread(() -> {while (true) {try {if (isDisContentWithServer()) {while (true) {try {socket = new Socket(IP, PORT);outputStream = socket.getOutputStream();System.out.println(new Date() + ":重新建立连接成功");break;} catch (IOException e) {System.out.println(new Date() + ":尝试重新建立连接失败");try {Thread.sleep(2000);} catch (InterruptedException ex) {throw new RuntimeException(ex);}}}}} catch (Exception e) {e.printStackTrace();}}}).start();}public static boolean isDisContentWithServer() {try {outputStream.write(("发送数据").getBytes(StandardCharsets.UTF_8));Thread.sleep(2000);return false;} catch (Exception e) {return true;}}
}

演示截图

开启服务器 – 客户端建立连接
在这里插入图片描述

断开Wifi – 客户端尝试重新建立连接 – 重新打开Wifi – 连接成功
在这里插入图片描述

总结

本次断网重连演示完美结束,如有疑问,可在评论区进行提问

相关文章:

Java的Socket通信的断网重连的正确写法

Java的Socket通信的断网重连的正确写法 Socket通信的断网重连介绍客户端与服务端源码演示截图本地演示服务器演示演示截图 总结 Socket通信的断网重连介绍 针对于已经建立通信的客户端与服务器,当客户端与服务器因为网络问题导致网络不通而断开连接了或者由于服务器…...

Rocketmq--消息发送和接收演示

使用Java代码来演示消息的发送和接收 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.0.2</version> </dependency> 1 发送消息 消息发送步骤: 创建…...

ArcGIS Pro将SHP文件转CAD并保留图层名称

相信大家应该都使用过ArcGIS将SHP文件转CAD格式&#xff0c;转换过后所有的要素都在一个图层内&#xff0c;那么有没有办法将SHP文件某个字段的值作为CAD的图层名字呢&#xff0c;答案是肯定的&#xff0c;这里就为大家介绍一下ArcGIS Pro转CAD文件并且保留图层名称的方法&…...

GEE:使用for循环合成时间序列影像

作者:CSDN @ _养乐多_ 在本博客中,我们将介绍如何使用Google Earth Engine创建一个时间序列图像集合,以便进行时间序列分析或生成动态图像。 文章目录 一、核心代码二、代码解释三、示例代码链接一、核心代码 // 创建一个空的 image 图像集合 var imagelist = ee.List([])…...

flink1.13.2版本的对应的hive的Hcatalog的使用记录

依赖版本要求<hive.version>3.1.2</hive.version><flink.version>1.13.2</flink.version><hadoop.version>3.3.2</hadoop.version><scala.binary.version...

STM32 ADC介绍和应用

目录 1.ADC是什么&#xff1f; 2.ADC的性能指标 3.ADC特性 4.ADC通道 5.ADC转换顺序 6.ADC触发方式 7.ADC转化时间 8.ADC转化模式 扫描模式 单次转换/连续转换 9.ADC实验 使用ADC读取烟雾传感器的值 代码实现思路&#xff1a; 1.ADC是什么&#xff1f; 全称&#…...

vue项目打包_以生产环境prod模式打包_vue-cli-service 不是内部或外部命令,也不是可运行的程序---vue工作笔记0025

打开命令行: 首先执行npm install 不执行会报错: npm run build:prod --scripts-prepend-node-pathauto 然后再这样执行就是以生产环境模式打包了....

FreeSWITCH的liberal dtmf

sip profile配置liberal-dtmf为true&#xff0c;或者通道变量rtp_liberal_dtmf为true&#xff0c;其含义就是不挑剔协商的DTMF&#xff0c;offer rfc2833并接受远端的rfc2833 和SIP INFO。 sofia.c的部分内容&#xff1a; // 收到sip info的处理 void sofia_handle_sip_i_inf…...

透明度模糊Android实现

最近有个需求&#xff0c;需要透明度加模糊&#xff0c;并且无法通过Glide的方式实现。研究后发现有一个第三方库可以实现这个效果 implementation com.github.Dimezis:BlurView:version-2.0.3在activity的onCreate&#xff08;&#xff09;方法中 实现效果 可以看到上边的bar…...

JavaScript学习笔记04

JavaScript笔记04 方法 定义方法 当一个函数是一个对象的属性时&#xff0c;称之为方法。例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script>let p…...

18 Python的sys模块

概述 在上一节&#xff0c;我们介绍了Python的os模块&#xff0c;包括&#xff1a;os模块中一些常用的属性和函数。在这一节&#xff0c;我们将介绍Python的sys模块。sys模块提供了访问解释器使用或维护的变量&#xff0c;以及与解释器进行交互的函数。 通俗来讲&#xff0c;sy…...

Spring Boot 各版本的支持时间

1. Spring Boot 各版本的支持时间 Spring Boot 2.7 的版本&#xff0c;支持到2023-11-18&#xff0c;之后就要停止支持了。 按照官网的数据&#xff0c;3.0 的版本也是到2023年11月就停止支持了。如果要转到SpringBoot3&#xff0c;直接从3.1开始吧。到写这篇文章时&#xff…...

华为云云耀云服务器L实例评测|Git 私服搭建指南

前言 本文为华为云云耀云服务器L实例测评文章&#xff0c;测评内容是 云耀云服务器L实例 Git 私有服务器搭建指南 系统配置&#xff1a;2核2G 3M Ubuntu 20.04 我们平时在使用代码托管服务的时候&#xff0c;可能某些代码托管平台对成员有限制&#xff0c;或是由于内容原因会对…...

Linux下的Swap内存

目录 一、Swap简介二、Swap内存查看三、Swap内存释放1、关闭swap2、查看关闭进度2、开启swap 一、Swap简介 swap space 是磁盘上的一块区域&#xff0c;可以是一个分区&#xff0c;也可以是一个文件。所以具体的实现可以是 swap分区 也可以是 swap文件。 当系统物理内存吃紧时…...

Unity中程序集dll

一&#xff1a;前言 一个程序集由一个或多个文件组成&#xff0c;通常为扩展名.exe和.dll的文件称为程序集&#xff0c;.exe是静态的程序集&#xff0c;可以在.net下直接运行加载&#xff0c;因为exe中有一个main函数(入口函数&#xff09;&#xff0c;.dll是动态链接库&#…...

识典百科取代快懂百科,如何在识典百科创建词条?

我们一个营销项目里面有四个百科词条的创建&#xff0c;在执行过程中遇见了快懂百科升级&#xff0c;创建词条请前往识典百科&#xff0c;看这个意思字节跳动是要把快懂百科升级整合到识典百科了。 快懂百科升级整合进入识典百科 近年来&#xff0c;字节跳动动作不断&#xff0…...

入门python

[NOIP2006 普及组] 明明的随机数 题目描述 明明想在学校中请一些同学一起做一项问卷调查&#xff0c;为了实验的客观性&#xff0c;他先用计算机生成了 N N N 个 1 1 1 到 1000 1000 1000 之间的随机整数 ( N ≤ 100 ) (N\leq100) (N≤100)&#xff0c;对于其中重复的数字…...

基于vue的黑马前端项目小兔鲜

目录 项目学习 初始化项目 建立项目 引入elementplus elementPlus主题设置 配置axios 路由 引入静态资源 自动导入scss变量 Layout页 组件结构快速搭建 字体图标渲染 一级导航渲染 吸顶导航交互实现 Pinia优化重复请求 Home页 分类实现 banner轮播图 …...

细节决定成败!jdbc的List<?> qryList4Sql(String sql)报错-标志符过长

问题产生背景&#xff1a; 在写sql时&#xff0c;想着简单直接就偷懒了&#xff0c;没有看清细节 操作步骤跟发现问题&#xff1a; 1. sql语句的执行选用的是jdbc提供的List<?> qryList4Sql(String sql) 方法 2&#xff0c;这是我的sql语句(简化处理) String sql "…...

ChatGLM Pytorch从0编写Transformer算法

预备工作 # !pip install http://download.pytorch.org/whl/cu80/torch-0.3.0.post4-cp36-cp36m-linux_x86_64.whl numpy matplotlib spacy torchtext seaborn import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import math, copy, tim…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...