网上看了很多关于Socket的Demo,用起来挺好用也简单,不过都在断开连接时,都没有做好相关处理,导致每次主动断开时,会报错
如:
java.net.SocketException: Socket closed at 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 sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:161) at java.io.BufferedReader.readLine(BufferedReader.java:324) at java.io.BufferedReader.readLine(BufferedReader.java:389) at com.idea_a.its.robot.http.SocketUtil.connectionData(SocketUtil.java:136) at com.idea_a.its.robot.TryBServer$1$1.success(TryBServer.java:38) at com.idea_a.its.robot.http.SocketUtil.connectSocket(SocketUtil.java:55) at com.idea_a.its.robot.TryBServer$1.run(TryBServer.java:34) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
具体原因是在执行socket.close();的同时,相关的BufferedReader还在等待接收数据。
所以在断开之前需要执行相关输入输出的关闭动作。
socket.shutdownInput();socket.shutdownOutput(); 并需要确保都关闭后(socket.isInputShutdown() socket.isOutputShutdown()),才进行BufferedReader的关闭,最终才是关闭socket;
就以客户端为例:完整代码如下(根据需要自行增减):
package com.bug01.trysocket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; public class SocketClientUtil { private static final String ADDRESS = "127.0.0.1"; private static final String PORT = "6666"; private Socket socket = null; private BufferedReader br; private static SocketClientUtil instance = null; // 此处使用单例模式 public static SocketClientUtil getInstance() { if (instance == null) { synchronized (SocketClientUtil.class) { if (instance == null) { instance = new SocketClientUtil(); } } } return instance; } /** * 连接socket */ public void connectSocket(SocketConnCallBack back) throws IOException { try { socket = new Socket(ADDRESS, Integer.parseInt(PORT)); back.success(); } catch (IOException e) { e.printStackTrace(); back.failure(); socket = null; } catch (Exception e) { e.printStackTrace(); back.failure(); } } /** * 发送数据 * * @param message */ public void sendData(String message) throws IOException { //判定是否socket已链接,如果未链接则尝试链接。 if (socket == null) { connectSocket(new SocketConnCallBack() { @Override public void success() { } @Override public void failure() { } }); } //如果尝试链接失败,则上报异常。 if (socket == null) { throw new IOException("Socket Connect to Server Error."); } //输出流 OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); //向服务端写入数据 pw.println(message); pw.flush(); } /** * 接受数据 */ public void SetListener(SocketCallBack back) throws IOException { //输入流 InputStream is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); //接收服务器的相应 String reply = null; while (!((reply = br.readLine()) == null)) { back.responseData(reply.trim()); } } /** * 关闭 */ public void close() throws IOException { if (socket == null) return; socket.shutdownInput(); socket.shutdownOutput(); do { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } while (!socket.isInputShutdown() || !socket.isOutputShutdown()); br.close(); socket.close(); socket = null; } public interface SocketCallBack { void responseData(String data); } public interface SocketConnCallBack { //socket连接成功 void success(); //socket链接失败 void failure() throws IOException; } }
原文地址:https://www.cnblogs.com/vingxu/p/10740355.html
时间: 2024-11-09 00:19:27