Socket 通信中read方法阻塞接收的问题

客户端:

public class Client {
    public static void main(String[] args) throws IOException {
//        与服务器建立连接
        Socket socket = new Socket("localhost", 1234);
//        向服务器发送消息
        OutputStream os = socket.getOutputStream();
        os.write("hello,serve!".getBytes());
//        等待服务器返回消息
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer,0,len);
        }
//        打印服务器发来的数据
        System.out.println(baos);
//        关闭资源
        baos.close();
        is.close();
        os.close();
        socket.close();

    }
}

服务器:

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(1234);
//        等待连接 阻塞方法
        Socket client = serverSocket.accept();
        System.out.println("客户端成功建立连接,等待客户端发送信息...");
        InputStream is = client.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
//        读取信息
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer,0,len);
        }
//        打印客户端发来的数据
        System.out.println(baos);
//        向服务器返回消息
        OutputStream os = client.getOutputStream();
        os.write("hello,client!".getBytes());
//        关闭资源
        os.close();
        baos.close();
        is.close();
        client.close();
        serverSocket.close();

    }
}

测试方法和期待的现象:
先启动Server服务器,等待客户端的连接,然后启动Client客户端,向服务器发送hello,serve!,服务器接收到信息后,向客户端返回hello,client!

实际现象:
服务器未打印出客户端发送的信息,服务器和客户端被阻塞住

原因分析:
代码在Server类的read()方法中阻塞住,服务器一直等待接受客户端的数据,并不知道客户端的数据已经发送完毕,没有返回-1,查看API如下:
在这里插入图片描述
解决方法1:
调用shutdownOutput方法()方法关闭输出流,或者close()方法直接关闭socket,这两种方法都会使对端的read方法返回-1,代码继续向下执行,区别是socket.close() 会将socket关闭连接,如果服务器给客户端反馈信息,此时客户端是收不到的,而socket.shutdownOutput()是将输出流关闭,此时,如果服务器有信息反馈,则客户端是可以正常接收的,修改客户端代码如下:

public class Client {
    public static void main(String[] args) throws IOException {
//        与服务器建立连接
        Socket socket = new Socket("localhost", 1234);
//        向服务器发送消息
        OutputStream os = socket.getOutputStream();
        os.write("hello,serve!".getBytes());
//		  关闭输出流
        socket.shutdownOutput();
//        等待服务器返回消息
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer,0,len);
        }
//        打印服务器发来的数据
        System.out.println(baos);
//        关闭资源
        baos.close();
        is.close();
        os.close();
        socket.close();
    }
}

解决方法2:
发送数据时,约定数据的首部固定字节数为数据长度。这样读取到这个长度的数据后,就不继续调用read方法

解决方法3:
发送数据时,最后输出 \n 或 \r 作为数据传输终符
修改代码如下:
客户端:

        os.write("hello,serve!".getBytes());
        os.write("\n".getBytes());

服务器:

        byte[] buffer = new byte[1024];
        StringBuilder sb = new StringBuilder();
        int len;
//        读取信息
        while ((len=is.read(buffer)) != -1) {
            String s = new String(buffer, 0, len);
            if (s.equals("\n")) {
                break;
            }
            sb.append(s);
        }
//        打印客户端发来的数据
        System.out.println(sb);

参考文章:
https://www.cnblogs.com/gaoqiri/p/10055610.html
https://www.jianshu.com/p/cde27461c226
https://wiki.jikexueyuan.com/project/java-socket/socket-read-deadlock.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鑫宇_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值