前言:

如标题所示,本文主要罗列下Socket编程中的那些常见异常,通过实战的方式来模拟这些异常。

1.java.net.BindException: Address already in use: JVM_Bind

原因:就是当前端口号已经被其他进程占用了。

模拟:创建两个ServerSocket,以相同的端口号启动。

ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 9999));ServerSocket serverSocket2 = new ServerSocket();
serverSocket2.bind(new InetSocketAddress("localhost", 9999));

此时就会出现该异常

2.java.net.ConnectException: Connection refused: connect

原因:当客户端通过Socket(ip,port)创建对远端ip:port的连接时,当对应的ip或port并不存在时(或者ip存在但是在执行port上没有进程在监听),则会报当前错

模拟:服务端以9999端口启动,客户端以8888端口连接

// 服务端启动
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 9999));// 客户端启动
Socket socket = new Socket("localhost", 8888);

3.java.net.SocketTimeoutException: connect timed out

原因:客户端在规定时间内没有连接上服务端。这个报错的具体原因有很多种

模拟:笔者在Mac上启动ServerSocket,并打开防火墙,阻止所有传入连接;然后在Windows电脑上开启Socket连接

服务端代码

SocketAddress address = new InetSocketAddress("localhost", 9999);
ServerSocket ss = new ServerSocket();
ss.bind(address);
// 接收请求
Socket s = ss.accept();// 直接sleep
Thread.sleep(1000000);

客户端代码

public class Client {static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) {connectTime();}public static void connectTime() {Socket socket =  new Socket();try {System.out.println("begin time:" + format.format(new Date()));// 连接服务端ip:portsocket.connect(new InetSocketAddress("192.168.3.18", 9999), 3000);System.out.println(socket.isConnected());} catch (IOException e) {e.printStackTrace();} finally {System.out.println("end time:" + format.format(new Date()));}}
}

测试:

先启动服务端,再启动客户端,可以看到客户端的控制台信息如下

begin time:2022-06-18 11:54:19
java.net.SocketTimeoutException: connect timed outat java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)at java.net.Socket.connect(Socket.java:589)at sockettimeout.Client.connectTime(Client.java:27)at sockettimeout.Client.main(Client.java:19)
end time:2022-06-18 11:54:22

连接花费时间为3秒,就是我们设置的连接超时时间

4.java.net.SocketTimeoutException: Read timed out

原因:客户端或服务端Socket设置了读超时时间,在指定时间内没有获取到结果,则会抛出该异常

模拟:服务端监听到连接后直接sleep,客户端在连接成功后从InputStream中获取数据,一直等待到超时

服务端代码

SocketAddress address = new InetSocketAddress("localhost", 9999);
ServerSocket ss = new ServerSocket();
ss.bind(address);
// 接收请求
Socket s = ss.accept();// 直接sleep
Thread.sleep(1000000);

客户端代码

static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) {try {Socket socket = new Socket("localhost", 9999);// 设置超时时间为5秒socket.setSoTimeout(5000);socket.setKeepAlive(true);InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];System.out.println("begin time:" + format.format(new Date()));// 在这里阻塞read方法,一直到超时为止while (inputStream.read() != -1) {inputStream.read(bytes);}} catch (Exception e) {e.printStackTrace();} finally {System.out.println("end time:" + format.format(new Date()));}
}

测试:

先启动服务端,再启动客户端,可以看到客户端的控制台信息如下

begin time:2022-06-18 11:16:04
java.net.SocketTimeoutException: Read timed outat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)at java.net.SocketInputStream.read(SocketInputStream.java:224)at sockettimeout.Client.main(Client.java:27)
end time:2022-06-18 11:16:09

end-start正好等于我们设置的Socket.setSoTimeout(5000) 5秒钟。

5.java.net.SocketException: Socket closed

原因:这种情况在客户端和服务端都有可能发生。主要原因是:在socket关闭了连接后,又发起了读写操作

模拟:客户端Socket创建完成,在调用close()方法后,再次发起写操作

5.1 服务端代码

下面展示的是一个完整的服务端代码,后续会采用该示例

public class BIOServerSocket {private String address;private int port;public BIOServerSocket(String address, int port) {this.address = address;this.port = port;}public void startServer() {try {ServerSocket serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(address, port));System.out.println("bio server start...");while (true) {Socket clientSocket = serverSocket.accept();System.out.println("client connect...");// 写入 threadServerWriteThread serverWriteThread = new ServerWriteThread(clientSocket);serverWriteThread.start();// 读取数据read(clientSocket);}} catch (IOException e) {e.printStackTrace();}}private void read(Socket clientSocket) {try {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));String msg = "";while ((msg = bufferedReader.readLine()) != null) {System.out.println("receive msg: " + msg);if (msg.equals("bye")) {bufferedReader.close();clientSocket.close();}}} catch (IOException e) {try {clientSocket.close();} catch (IOException ex) {ex.printStackTrace();}e.printStackTrace();}}public static void main(String[] args) {String address = "localhost";int port = 9999;BIOServerSocket bioServerSocket = new BIOServerSocket(address, port);bioServerSocket.startServer();}
}/*** 从Scanner获取输入信息,并写回到client*/
class ServerWriteThread extends Thread {private Socket socket;private PrintWriter writer;private Scanner scanner;public ServerWriteThread(Socket socket) throws IOException{this.socket = socket;scanner = new Scanner(System.in);this.writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);}@Overridepublic void run() {String msg = "";try {while ((msg = scanner.nextLine()) != null) {if (msg.equals("bye")) {socket.close();break;}writer.println(msg);}} catch (Exception e) {e.printStackTrace();}}
}

客户端代码

try {Socket socket =  new Socket("localhost", 9999);OutputStream outputStream = socket.getOutputStream();// 第一次写数据outputStream.write(11);// 关闭socketsocket.close();// 第二次写数据outputStream.write(12);
} catch (IOException e) {e.printStackTrace();
}

测试:

先启动服务端,再启动客户端,可以看到客户端的控制台输出如下信息

java.net.SocketException: Socket closedat java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118)at java.net.SocketOutputStream.write(SocketOutputStream.java:134)at sockettimeout.Client.socketClose(Client.java:32)at sockettimeout.Client.main(Client.java:20)

6.java.net.SocketException: Software caused connection abort: socket write error

原因:该问题有可能发生在客户端或服务端。主要因为:当一端的socket被关闭后,另一端仍进行数据读写

注意:与5的不同在于,5中的示例是当前socket关闭后又继续发送数据,而6该问题是对端关闭了socket,当前端仍进行数据读写

模拟:服务端接收到连接后,等待一段时间则关闭该socket,而此时客户端继续读写

服务端代码

SocketAddress address = new InetSocketAddress("localhost", 9999);
ServerSocket ss = new ServerSocket();
ss.bind(address);// 接收连接
Socket s = ss.accept();Thread.sleep(3000);s.close();

客户端代码:

try {System.out.println("begin time:" + format.format(new Date()));Socket socket =  new Socket("localhost", 9999);OutputStream outputStream = socket.getOutputStream();outputStream.write(11);System.out.println("send 11");Thread.sleep(1000);outputStream.write(12);System.out.println("send 12");Thread.sleep(1000);outputStream.write(13);System.out.println("send 13");Thread.sleep(1000);outputStream.write(14);System.out.println("send 14");Thread.sleep(1000);outputStream.write(15);System.out.println("send 15");
} catch (Exception e) {e.printStackTrace();
} finally {System.out.println("end time:" + format.format(new Date()));
}

测试:先启动服务端,再启动客户端,控制台结果如下:

begin time:2022-06-18 12:16:14
send 11
send 12
send 13
java.net.SocketException: Software caused connection abort: socket write errorat java.net.SocketOutputStream.socketWrite0(Native Method)at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)at java.net.SocketOutputStream.write(SocketOutputStream.java:134)at sockettimeout.Client.connectReset(Client.java:38)at sockettimeout.Client.main(Client.java:20)
end time:2022-06-18 12:16:17

注意:还有可能遇到些别的异常信息,如connect reset by peer,实际是与当前场景类似的。

参考:

java.net.SocketException四大异常解决方案_hzp666的博客-CSDN博客_socketexception

Java SDK报错:SocketTimeoutException - 表格存储 - 阿里云 SocketTimeoutException的一些场景

Socket常见异常场景模拟实战相关推荐

  1. 常见的Socket网络异常场景分析

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 在目前微服务的背景下,网络异常越来越常见了,而有一些网络异常非常模糊,理解什么情况下会导致什么异常,还是有一定难度 ...

  2. ECONNABORTED,Socket 常见连接错误之一,原因分析 + 解决办法

    原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重. 前言 通过本篇,你将简单了解到 Socket 连接错误-- ECONNABORTED [产生的原因],还有[避免的方法],结论直接见最后的 ...

  3. 机器视觉、目标检测常见应用场景

    机器视觉.目标检测常见应用场景 人脸人体检测 智能美肤 在保持皮肤质感的同时,自动对脸部进行匀肤.去瑕疵(痘.痘印.雀斑等)操作,并对全身皮肤进行美白. 智能瘦脸 系统自动检测并分析人脸五官特征,生成 ...

  4. 一种隐蔽性较高的Java ConcurrentModificationException异常场景

    前言 在使用Iterator遍历容器类的过程中,如果对容器的内容进行增加和删除,就会出现ConcurrentModificationException异常.该异常的分析和解决方案详见博文<Jav ...

  5. JS闭包的理解及常见应用场景

    JS闭包的理解及常见应用场景 一.总结 一句话总结: 闭包是指有权访问另一个函数作用域中的变量的函数 1.如何从外部读取函数内部的变量,为什么? 闭包:f2可以读取f1中的变量,只要把f2作为返回值, ...

  6. 串口服务器工作方式及常见异常故障问题排除方法介绍

    串口设备联网服务器就像一台带CPU.实时操作系统和TCP/IP协议的微型电脑,方便在串口和网络设备中传输数据.您可以在世界任何位置通过网络,用您的计算机来存取,管理和配置远程的设备.但是我们在实际使用 ...

  7. vs 启动调用的目标发生异常_如何解决不可测、异常场景的问题?

    阿里QA导读:在软件研发过程中,发布前跨多个系统的联调测试是不可或缺的一环,而在联调过程中,经常会遇到一些比较棘手的困难,阻塞整个联调进程.其中比较典型的有:第三方的研发节奏不一致,导致无法联调:下游 ...

  8. java内存溢出模拟_模拟实战排查堆内存溢出(java.lang.OutOfMemoryError: Java heap space)问题...

    前言: 模拟实战中排查堆内存溢出(java.lang.OutOfMemoryError: Java heap space)的问题. 堆内存溢出的原因:一般都是创建了大量的对象,这些对象一直被引用着,无 ...

  9. 面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)

    文章目录 对JS闭包的理解及常见应用场景(闭包的作用) 1.变量作用域 2.如何从外部读取函数内部的变量? 3.闭包概念 4.闭包用途 5.闭包的理解 6.闭包应用场景 setTimeout传参 回调 ...

最新文章

  1. 计算机视觉方向简介 | 视觉惯性里程计(VIO)
  2. C#如何判断线程池中所有的线程是否已经完成(转)
  3. 为什么在MM32中的MicroPython中无法打开二进制文件呢?
  4. linux 批量删除
  5. Android面试题集合
  6. java 协程_你真的了解kotlin的协程么?
  7. c语言prog.c: in function 'main':,C语言 tr1 :: function和tr1 :: bind
  8. Java前台线程与后台线程
  9. 练习4.4、4.5、4.6、4.7
  10. Android开发学习:在Eclipse中导入Android项目方法
  11. java中的字符,字符串,数字之间的转换
  12. 微信小程序文本溢出省略号(···)
  13. HDOJ 2896 病毒侵袭(AC自动机入门)
  14. 32-SIFI特征点提取(EmguCV学习)
  15. 离散数学之矩阵关系运算
  16. heartbeat和keepalive
  17. JavaScript中的symbol对象
  18. PMBOK(第六版) PMP笔记——《七》第七章(项目成本管理)
  19. 获取PC 服务器 可用的GPU
  20. Testin云测试平台

热门文章

  1. PlantSimulation学习笔记:3种故障模式(Failure relates to)详解
  2. 【论文阅读004】:V-Fuzz: Vulnerability Prediction-Assisted Evolutionary Fuzzing for Binary Programs
  3. 全球快递查询-全国快递物流查询-顺丰快递-国内外1500+快递接口-物流信息追踪接口
  4. 使用qt写吃豆人游戏
  5. 引力理论会失效?引力理论与量子理论相冲突之谜
  6. 国内软件外包业首次大合并
  7. python怎在excel-Python操作Excel之xlsx文件
  8. Java ADT——一元二次多项式
  9. “暴跌之王”量子链:曾经“放卫星”引轰动,如今币价较最高点跌去97.7%
  10. linux网络编程 no route to host 解决方案