因为网络传输的非实时性,你就不能把你程序写成单次顺序执行的方式,因为,在你的程序去检查available的时候,实际上另一端可能还没有发送数据,或对方网络拥挤,要发给你的数据包还在队列中。所以你调用 available 会返回0。

你看看别人写的程序,一般不是用异步框架,如:mina,就是用线程不断扫描IO流,就是出于这个原因。

而且 available 返回的字节数也不一定就是对方实际发送数据的长度,因为,如果数据长度过大的话,在实际的网络发送过程中,会对数据进行分段,分多次发送,而 available  只返回本次的可用字节数,这就是我开始讲的第二点“网络传输的不连续性”。

所以,你如果对网络游戏的网络数据包有研究的话,你会发现,他们一般都会将本次要传输的字节数,放到整个数据包的开头的某一段位置,如:WOW。也就是说要自己设计网络传输的数据结构来实现发送数据的长度,才是最可靠的。

先看看下面这段代码(有删节)

public static String send(String sendurl, String sendText) throws Exception {
   URL url = null;
   URLConnection uc = null;

//建立连接、输出数据等;

String strReceive = ""; 
   try {
    InputStream is = uc.getInputStream();

DataInputStream in = new DataInputStream(is);
   int blockLen = in.available();
    byte block[] = new byte[blockLen];
   for (int readLen = -9999; readLen != -1;) {
      readLen = in.read(block);

if (readLen != -1)
       strReceive = strReceive + new String(block);
     }
    is.close();
    in.close();
   } catch (IOException e) {
    logger.info("httpl接收错误1:" + e.getMessage());
   }
   return strReceive;
}

注意红色字体那几行。blockLen被用来创建一个字节数组block,block作为数据缓冲来读取inputstream里的数据。然后循环从inputstream中读取数据,写入block中。

考虑一种情况。如果网络阻塞了,inputstream已经打开,但是数据却还没有传输过来,会发生什么?

inputstream.available()方法返回的值是该inputstream在不被阻塞的情况下一次可以读取到的数据长度。如果数据还没有传输过来,那么这个inputstream势必会被阻塞,从而导致inputstream.available返回0。而对inputstream.read(byte[] b)而言,如果b的长度等于0,该方法将返回0。

回头看看这个循环体的结束条件,是readLen == -1时跳出。显然,上面提到的网络阻塞情况发生之后,代码将陷入这个死循环当中。

这是我们在工程应用中遇到的一个问题。由外包商提供的工具jar包中的这段代码,直接将我们的服务器拉进了死循环。

我们的解决方法,是将整个接收与发送的方法进行改写,使用了下面的这段代码:

HttpClient client = new HttpClient();
    PostMethod method = new PostMethod(prpUrl);
    method.setRequestBody(sendstr);
    method.getParams().setParameter(
      HttpMethodParams.HTTP_CONTENT_CHARSET, "GBK");
    client.executeMethod(method);
    // rtnXml = method.getResponseBodyAsString();
    InputStream txtis = method.getResponseBodyAsStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(txtis));
    String tempbf;
    StringBuffer html = new StringBuffer(100);
    while ((tempbf = br.readLine()) != null) {
     html.append(tempbf);
    }
    rtnXml = html.toString();

method.releaseConnection();

确确实实的,解决了问题。

如果仍然要采用原方法中手动打开输入流、建立缓冲区、循环读取数据的方法,那么不应该用available这个字段来作为缓冲区的初始长度。可以考虑手工设定一个固定值;或者读取http报文头的content-length属性值。最后的这种方式没有尝试过。

InputStream 中available 的使用相关推荐

  1. android InputStream中read()与read(byte[] b)

    今天,简单讲讲android里的  InputStream的read()读取文件的使用. 这两个方法在抽象类InputStream中都是作为抽象方法存在的, JDK API中是这样描述两者的: r ...

  2. InputStream中通过mark和reset方法重复利用缓存

    通过缓存InputStream可重复利用一个InputStream,但是要缓存一整个InputStream内存压力可能是比较大的.如果第一次读取InputStream是用来判断文件流类型,文件编码等用 ...

  3. java清空inputstream中的流_Java 流处理

    数据流 1.I/O流概述 大部分程序都需要输入/输出处理,比如从键盘读取数据.向屏幕中输出数据.从文件中读或者向文件中写数据.在一个网络连接上进行读写操作等.在Java中,把这些不同类型的输入.输出源 ...

  4. java stream 多次读取_多次从具有大量数据的Java InputStream中读取

    我想知道什么是从Java InputStream多次读取字节并在流很大时仍然有效的最佳方法. 假设我有以下代码: public void handleBytes(InputStream in) { d ...

  5. java 文件inputstream_java – 如何在InputStream中接收多个文件并相应地处理它?

    我想收到从客户端上传的多个文件.我上传了多个文件并使用JAX-RS(Jersey)请求我的服务器端( Java). 我有以下代码, @POST @Consumes(MediaType.MULTIPAR ...

  6. android读取工程目录下的文件,Android编程实现读取工程中的txt文件功能

    本文实例讲述了Android编程实现读取工程中的txt文件功能.分享给大家供大家参考,具体如下: 1. 众所周知,Android的res文件夹是用来存储资源的,可以在res文件夹下建立一个raw文件夹 ...

  7. request中的内容存储_宜信开源|调用链系列(3):解读UAVStack中的调用链技术...

    拓展阅读:宜信开源|调用链系列(1):解读UAVStack中的贪吃蛇 调用链系列(二):解读UAVStack中的贪吃蛇-调用链 在Java中,HTTP协议的请求/响应模型是由Servlet规范+Ser ...

  8. [五] JavaIO之InputStream OutputStream简介 方法列表说明

    InputStream 和 OutputStream 对于字节流的输入和输出 是作为协议的存在 所以有必要了解下这两个类提供出来的基本约定 这两个类是抽象类,而且基本上没什么实现,都是依赖于子类具体的 ...

  9. java inputstream 回退_系统学习 Java IO (十)----回退流 PushbackInputStream

    PushbackInputStream 旨在从 InputStream 解析数据时使用. 有时您需要先读取几个字节以查看将要发生的事情,然后才能确定如何解释当前字节, PushbackInputStr ...

最新文章

  1. 中英文标点符号切换的组合键_易混标点符号:一字线(—)、短横线(-)、浪纹线(~)...
  2. 生成 excel 直接用 httpServletResponse 输出
  3. spring IOC 装配一个bean
  4. codelite linux 安装,CodeLite + MinGW环境安装
  5. angular6 设置全局变量_Angularjs 设置全局变量的方法总结
  6. 在mysql的操作界面中,如何清屏幕
  7. Delphi 正则表达式起步
  8. Top Down Operator Precedence - 自顶向下算符优先分析法
  9. php开发完整教程 pdf,PHP完整教程.pdf
  10. php本地打开pdf文件_用PHP在web浏览器中打开PDF文件的方法
  11. 用postman测试post接口的设置步骤,参数为json
  12. 同一个服务器装oracle,windows下同一台服务器上装有两个ORACLE数据库实例,通过命令启停数据库...
  13. python 负数变正数_numpy正数相乘变负数的解决办法
  14. excel函数应用:Column函数替代列参数提高公式灵活性
  15. 从事电商Java后端一年的思考与总结
  16. android 副屏,安卓收银机双屏(副屏)异显,主副屏通讯
  17. 议题预告 | Pulsar Summit Asia 2021:Day 1 -主题演讲
  18. cve-2005-1794
  19. torch.ones(),torch.add(),torch.zeros(),torch.squeeze()
  20. 构建之法 20162316刘诚昊

热门文章

  1. 计算机卡 怎么检测,卡硬工具箱怎么测试CPU 轻松了解自己的处理器性能
  2. 测试CarbonData
  3. 【网络】MTU相关网络丢包问题分析处理
  4. ubuntu中使用vi编辑无法使用上下左右移动键的处理方式
  5. 【论文笔记】Segmenting Transparent Object in the Wild with Transformer
  6. DM(达梦)数据库简介
  7. spacewar无法连接至远程计算机,Start-DscConfiguration无法连接服务器计算机
  8. JDBC实现DBHelper类
  9. 华为大数据平台凭什么成为行业领跑者?
  10. 基于Java毕业设计智能化车辆管理综合信息平台源码+系统+mysql+lw文档+部署软件