客户端代码:

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的方法即可