网上看了很多关于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() 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;
}

就以客户端为例:完整代码如下(根据需要自行增减):

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;
}
}

Socket断开不报错(Java)的更多相关文章

  1. eclipse启动报错java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' befo

    报错: java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invo ...

  2. 开着idea,死机了,关机重启。重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification

    开着idea,死机了,关机重启.重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification. goo ...

  3. Eclipse启动报错Java was started but returned exit code=13

    启动Eclipse的时候报错Java was started but returned exit code=13,这个错误的原因是由于eclipse版本与jdk版本不符导致的,可能你的eclipse是 ...

  4. idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8

    问题如上面所叙: > idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8 解决方案: > Setting->Compiler->Ja ...

  5. 关于SpringMVC项目报错:java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/xxxx.xml]

    关于SpringMVC项目报错:java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/xxxx ...

  6. maven web 项目中启动报错 Java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet

    主要原因是maven项目里面的jar包吗,没有导入到项目中 maven web 项目中启动报错 Java.lang.ClassNotFoundException: org.springframewor ...

  7. zookeeper报错java.net.ConnectException: Connection refused: no further information

    zookeeper报错java.net.ConnectException: Connection refused: no further information 这是在linux 启动 https:/ ...

  8. 【原创】大叔问题定位分享(2)spark任务一定几率报错java.lang.NoSuchFieldError: HIVE_MOVE_FILES_THREAD_COUNT

    最近用yarn cluster方式提交spark任务时,有时会报错,报错几率是40%,报错如下: 18/03/15 21:50:36 116 ERROR ApplicationMaster91: Us ...

  9. 云笔记项目- 上传文件报错"java.lang.IllegalStateException: File has been moved - cannot be read again"

    在做文件上传时,当写入上传的文件到文件时,会报错“java.lang.IllegalStateException: File has been moved - cannot be read again ...

随机推荐

  1. 点击页面上的元素,页面删除removeChild()

    简单描述:最近做了一个图片上传,上传完成回显图片的时候,需要用到点击图片,从页面删除的效果,然后就找到了removeChild()方法,说实话,我刚看到的时候,就觉得这个问题已经解决了,但是却发现这个 ...

  2. pl/sql学习(5): 触发器trigger/事务和锁

    (一)触发器简单介绍 触发器是由数据库的特定时间来触发的, 特定事件主要包括以下几种类型: (1)DML: insert, update,delete 增删改 (2)DDL: create, alte ...

  3. Redis数据类型Hash

    Redis的Hash有点像一个对象(object),一个Hash里面可以存多个Key-Value对作为它的field,所以它通常可以用来表示对象.Hash里面能存放的值也能作为String类型来存储, ...

  4. [转]Windows 安装Kafka

    来源:https://www.cnblogs.com/liuyuhua/p/5329926.html https://www.cnblogs.com/xinlingyoulan/p/6054361.h ...

  5. 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)

    原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...

  6. c++中字符串的反转

    1.对于用char定义的字符串:使用string.h中的strrev函数 #include <iostream> #include <cstring> using namesp ...

  7. Mapjoin和Reducejoin案例

    一.Mapjoin案例 1.需求:有两个文件,分别是订单表.商品表, 订单表有三个属性分别为订单时间.商品id.订单id(表示内容量大的表), 商品表有两个属性分别为商品id.商品名称(表示内容量小的 ...

  8. webpack打包样式代码去重

    一.问题描述 控制台审查样式,同一个样式被导入很多遍,每调用一次@import "common.less";打包时都会多出一份类似的样式代码. 二.问题分析 补上... 三.解决方 ...

  9. 移动端click事件清除

    http://blog.csdn.net/zfy865628361/article/details/49512095

  10. centos7.4安装redis

    参考连接 https://blog.csdn.net/qq_19399235/article/details/78313633/