全部产品

java_net_SocketException

更新时间:2017-06-07 13:26:11

问题分析:

当服务端创建SocketServer时、客户端向服务端创建socket时、连接过程中发生错误时会抛出此类异常。此类异常主要有四种子类BindException、 ConnectException、NoRouteToHostException、PortUnreachableException,均可以被SocketException捕获。这四种子类的问题分析如下:

  1. BindException试图将套接字绑定到本地地址和端口时发生错误的情况下,抛出此异常。

  2. ConnectException试图将套接字连接到远程地址和端口时发生错误的情况下,抛出此异常,典型的方式是因为远程主机拒绝,例如远程主机不存在或并未监听此端口。

  3. NoRouteToHostException试图将套接字连接到远程地址和端口时发生错误的情况下,抛出此异常,一般原因是因为防火墙拦截或必经路由器中断引起的。

  4. PortUnreachableException在连接的数据报上已接收到 ICMP Port Unreachable 消息时,抛出该异常。

解决方案:当服务端创建SocketServer时、客户端向服务端创建socket时、连接过程中发生错误时会抛出此类异常,建议使用try catch finally块捕获异常并做好业务处理。

  1. 示例一

    1. java.net.SocketException: Connection reset
    2. at java.net.SocketInputStream.read(SocketInputStream.java:196)
    3. at java.net.SocketInputStream.read(SocketInputStream.java:122)
    4. at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
    5. at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
    6. at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
    7. at java.io.InputStreamReader.read(InputStreamReader.java:184)
    8. at java.io.BufferedReader.fill(BufferedReader.java:154)
    9. at java.io.BufferedReader.readLine(BufferedReader.java:317)
    10. at java.io.BufferedReader.readLine(BufferedReader.java:382)

问题分析:

该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。主要原因是在连接断开后的读和写操作引起的异常。

解决方案:

建议不要频繁建立过多socket请求导致服务器压力增大抛出SocketException,并使用try catch块捕获异常做后续处理。如果服务是幂等的,则客户端可以重试连接。如果不是幂等的,重试可能造成重复提单。

代码示例:

服务端代码:

  1. class SimpleServer implements Runnable {
  2. @Override
  3. public void run() {
  4. ServerSocket serverSocket = null;
  5. try {
  6. serverSocket = new ServerSocket(8111);
  7. serverSocket.setSoTimeout(3000);
  8. while (true) {
  9. try {
  10. Socket clientSocket = serverSocket.accept();
  11. BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  12. System.out.println("Client said :"+ inputReader.readLine());
  13. } catch (SocketTimeoutException e) {
  14. e.printStackTrace();
  15. }
  16. }
  17. }catch (SocketException e) {
  18. e.printStackTrace();
  19. }catch (IOException e1) {
  20. e1.printStackTrace();
  21. } finally {
  22. try {
  23. if (serverSocket != null) {
  24. serverSocket.close();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  31. }

客户端代码:

  1. class SimpleClient implements Runnable {
  2. @Override
  3. public void run() {
  4. Socket socket = null;
  5. try {
  6. socket = new Socket("localhost", 8111);
  7. PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
  8. System.out.println("Wait");
  9. Thread.sleep(15000);
  10. //throw new Exception("Random exception");
  11. outWriter.println("Hello Mr. Server!");
  12. }catch (SocketException e) {
  13. e.printStackTrace();
  14. }catch (InterruptedException e) {
  15. e.printStackTrace();
  16. } catch (UnknownHostException e) {
  17. e.printStackTrace();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. } finally {
  23. try {
  24. if (socket != null)
  25. socket.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  1. 示例二

    1. java.net.ConnectException: Connection refused: connect
    2. at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    3. at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    4. at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    5. at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    6. at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    7. at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    8. at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    9. at java.net.Socket.connect(Socket.java:579)
    10. at java.net.Socket.connect(Socket.java:528)
    11. at java.net.Socket.(Socket.java:425)
    12. at java.net.Socket.(Socket.java:208)

问题分析:服务端不能响应客户端的连接请求抛出异常。可能原因:ip或者端口写错、服务器宕机、防火墙等原因。

解决方案:

服务端不能响应客户端的连接请求抛出异常。建议检查ip或者端口正确、服务器可以访问、防火墙未限制。代码示例与示例一相同。

参考文献:

  1. https://docs.oracle.com/javase/7/docs/api/java/net/SocketException.html
  2. https://docs.oracle.com/javase/7/docs/api/java/net/BindException.html
  3. https://docs.oracle.com/javase/7/docs/api/java/net/ConnectException.html
  4. https://docs.oracle.com/javase/7/docs/api/java/net/NoRouteToHostException.html
  5. https://examples.javacodegeeks.com/core-java/net/connectexception/java-net-connectexception-how-to-solve-connect-exception/
  6. http://www.seotcs.com/blog/796.html
  7. https://my.oschina.net/xionghui/blog/508758