网上看了很多关于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;
代码如下:
/*** 关闭*/
public void close() throwsIOException {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;
}
就以客户端为例:完整代码如下(根据需要自行增减):
packagecom.bug01.trysocket;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.OutputStream;importjava.io.PrintWriter;importjava.net.Socket;public classSocketClientUtil {private static final String ADDRESS = "127.0.0.1";private static final String PORT = "6666";private Socket socket = null;privateBufferedReader br;private static SocketClientUtil instance = null;//此处使用单例模式
public staticSocketClientUtil getInstance() {if (instance == null) {synchronized (SocketClientUtil.class) {if (instance == null) {
instance= newSocketClientUtil();
}
}
}returninstance;
}/*** 连接socket*/
public void connectSocket(SocketConnCallBack back) throwsIOException {try{
socket= newSocket(ADDRESS, Integer.parseInt(PORT));
back.success();
}catch(IOException e) {
e.printStackTrace();
back.failure();
socket= null;
}catch(Exception e) {
e.printStackTrace();
back.failure();
}
}/*** 发送数据
*
*@parammessage*/
public void sendData(String message) throwsIOException {//判定是否socket已链接,如果未链接则尝试链接。
if (socket == null) {
connectSocket(newSocketConnCallBack() {
@Overridepublic voidsuccess() {
}
@Overridepublic voidfailure() {
}
});
}//如果尝试链接失败,则上报异常。
if (socket == null) {throw new IOException("Socket Connect to Server Error.");
}//输出流
OutputStream os =socket.getOutputStream();
PrintWriter pw= newPrintWriter(os);//向服务端写入数据
pw.println(message);
pw.flush();
}/*** 接受数据*/
public void SetListener(SocketCallBack back) throwsIOException {//输入流
InputStream is =socket.getInputStream();
br= new BufferedReader(newInputStreamReader(is));//接收服务器的相应
String reply = null;while (!((reply = br.readLine()) == null)) {
back.responseData(reply.trim());
}
}/*** 关闭*/
public void close() throwsIOException {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 interfaceSocketCallBack {voidresponseData(String data);
}public interfaceSocketConnCallBack {//socket连接成功
voidsuccess();//socket链接失败
void failure() throwsIOException;
}
}
当使用Java Socket编程时,直接调用`socket.close()`可能会导致`SocketException: Socket closed`错误。为避免此问题,应当在关闭Socket之前先调用`shutdownInput()`和`shutdownOutput()`方法,确保输入输出流关闭后再关闭Socket。这里提供了一个完整的客户端示例代码,展示了如何优雅地断开Socket连接。
587

被折叠的 条评论
为什么被折叠?



