java socket学习中遇到的流阻塞问题

在socket学习中 我们都知道要先创建一个websocket来作为服务器来与客户端建立链接,然后接收客户端发过来的请求的,但在学习过程中 却遇到了输入流在读取客户端发过来的数据时,一直阻塞住,不会执行后续代码的情况。

        ServerSocket serverSocket = new ServerSocket(8080);
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            byte[] buf = new byte[1024];
            int len;
 			 while ((len = inputStream.read(buf))>0) {
                System.out.println(new String(buf, 0, len));
            }
            inputStream.close();
            accept.close()

这里我们用浏览器去请求 http://localhost:8080/ 会发现 浏览器一直在转圈 程序一直在执行 未停下来
后续我们打断点发现 while ((len = inputStream.read(buf))>0) 代码一直卡在这一段 这里就是 inputStream.read 方法阻塞住了
分析:为什么会阻塞住呢 原因在于 我们的服务端会与浏览器(客户端) 建立个传输通道 从客户端读取到请求的信息 但是因为服务端 不清楚
浏览器还会不会发数据过来 所以通道一直未关闭 导致 一直阻塞住 一直在等客户端发数据

优化 :

            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            byte[] buf = new byte[1024];
            int len;
            while (inputStream.available() > 0) {
                len = inputStream.read(buf);
                System.out.println(new String(buf, 0, len));
            }

这里我们用了 inputStream.available() 方法来判断 流输入的 输入情况 这个available方法 在于可以第一次初略获取 数据的大概总字节 然后下次判断时 就会获取到剩下的数据量 如果是数据后续的总量发生了变化 例如 下次判断时 又传输了新数据过来 总量这里也能判断出来
用这个方法也会更加保险 因为available 是不会读取数据的 在这里只是获取个长度 实际读取数据的还是read方法 这样可以保证read方法的正常执行 且不会因为无法判断通道保留情况而阻塞住程序执行(尤其在网络传输中 要注意 上述问题 在本地传输文件这些 其实直接read判断即可 因为文件大小大概率不会改变 )

**InputStream的available()方法的作用是返回此输入流在不受阻塞情况下能读取的字节数。网络流与文件流不同的关键就在于是否“受阻”二字,网络socket流在读取时如果没有内容read()方法是会受阻的,所以从socket初始化的输入流的available也是为零的,所以要read一字节后再使用,这样可用的字节数就等于 available + 1。但文件读取时read()一般是不会受阻的,因为文件流的可用字节数 available = file.length(),而文件的内容长度在创建File对象时就已知了。
所以调用网络流(socket)的available()方法前,一定记得要先调用read()方法,这样才能避免获取为0的不正确情况。

当然为了保证能读取到缓存中的字节数 可以使用下面代码保证read的读取 此情况为针对 建立了连接 但还未开始发数据 即判断完了

            int buffLen=0;
            while (buffLen==0)
            {
                buffLen=inputStream.available();
            }

或者下面这种方式

            do {
                len=inputStream.read(buf);
                request.append(new String(buf,0,len));
            }while (inputStream.available()>0);

当然该段也是我个人的理解 如果有表述上的错误问题 欢迎指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值