TCP协议网络编程Exception in thread "main" java.net.SocketException: Connection reset报错解决

报错信息如下图:

 

 客户端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TcpSend {
public static void main(String[] args) throws IOException {
Socket sc = new Socket("127.0.0.1", 11223);
OutputStream out = sc.getOutputStream();
out.write("hello".getBytes());
// 接收服务器反馈
InputStream in = sc.getInputStream();
byte[] bys = new byte[1024];
int len=120;
while (in.read(bys)!=-1) {
System.out.println("客户端接收的数据:" + new String(bys, 0, len));
}
// len = in.read(bys);
// System.out.println("客户端接收的数据:" + new String(bys, 0, len));
sc.close();
}
}
务端代码
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpReceive {
public static void main(String[] args) throws IOException {
// 创建服务器端的 ServerSocket 对象(ServerSocket 类)
ServerSocket sc = new ServerSocket(11223);
// 监听客户端连接,创建一个监听套接字(返回一个 Socket 对象)
Socket ac = sc.accept();
// 获取输入流,读数据
InputStream in = ac.getInputStream();
byte[] bys = new byte[1024];
int len;
while ((len = in.read(bys))!=-1) {
            System.out.println("数据是:"+ new String(bys, 0, len));
}
// len = in.read(bys);
// System.out.println("数据是:" + new String(bys, 0, len));
// 发送客户端,进行反馈
OutputStream out = ac.getOutputStream();
out.write("我收到数据了".getBytes());
// 释放资源
sc.close();
}
}
主要原因:
通过查看 api 文档关于 read(byte[] b) 的介绍,从输入流读取一些字节数,并将它们存储到缓冲区b。实际读取的字节数作为整数返回。
该方法阻塞直到 1. 输入数据可用;2. 检测到文件结束;3. 抛出异常。
也就是说在上述几种情况下这个方法是一直阻塞的,所以当服务端和客户端都使用 while 循环的时候,无法判断 socket 的输入流中啥时候结束导致一直死循环。
解决上述问题:
  
经查询资料了解 Socket 对象的 shutdownOutput() 方法(描述:禁用此套接字的输出流。对于 TCP 套接字,任何先前写入的数据将被发送,
随后是 TCP 的正常连接终止序列),可用来对输出流增加结束标识,这样输入流通过 read
方法读数据时就能检测到文件结束而终止,不会出现一直阻塞情况。
    如图,在客户端和服务端的输出流代码后调用 Socket 对象的
shutdownOutput 的方法即可