NIO框架Cindy中HTTP解析的BUG- -

由于工作原因,想采用NIO技术,研究了一下CrmkyCindy框架。由于使用长连接方式,数据协议采用定长包头+不定长保体的方式,因而主要研究了其中的HTTP范例。在net.sf.cindy.example.http的HttpRequestDecoder中,发现了一个BUG。原始代码如下:

代码
  1. public Object decode(Session session, Packet packet) throws Exception {   
  2.     Buffer buffer = packet.getContent();   
  3.     int index = buffer.indexOf(TOKEN);   
  4.     if (index >= 0) {   
  5.         String[] headers = buffer.getString(Charset.UTF8,   
  6.                 index + TOKEN.length).split("/r/n");   
  7.   
  8.         HttpRequest request = new HttpRequest();   
  9.         parse(request, headers);   
  10.   
  11.         String contentLen = request.getParam("Content-Length");   
  12.         if (contentLen != null) {   
  13.             int len = Integer.parseInt(contentLen);   
  14.             if (buffer.remaining() >= len) {   
  15.                 byte[] content = new byte[len];   
  16.                 buffer.get(content);   
  17.                 request.setContent(content);   
  18.             } else {   
  19.                 return null;   
  20.             }   
  21.         }   
  22.         return request;   
  23.     }   
  24.     return null;   
  25. }  
<script type="text/javascript"></script>

假设:
第一步:http头已经读完,但http报文体长度不够,此时return null,等待下次读取;
第二步:在第二次下次读取时候http报文体时,又会重新检查TOKEN(/r/n/r/n),此时(index>=0)返回false,直接return null了。
此时,不能不确读取HTTP报文。其实,Cindy的接口中,定义了Attributes相关操作,因而可以把第一次读取的内容,通过session.setAttribute(HTTP_HEAD, request)缓存起来,下次读取是再继续。通过检查HTTP_HEAD的attribute是否存在,来绝对读取报文头还是报文体。修改后的代码如下:
代码

  1. public Object decode(Session session, Packet packet) throws Exception {   
  2.     Buffer buffer = packet.getContent();   
  3.     final String HTTP_HEAD = null;   
  4.     Object      request_obj = session.getAttribute(HTTP_HEAD);   
  5.     HttpRequest request_inst = null;   
  6.     if (request_obj==null) {    //读取HTTP头   
  7.         int index = buffer.indexOf(TOKEN);   
  8.         if (index >= 0) {   
  9.             String[] headers = buffer.getString(Charset.UTF8,   
  10.                     index + TOKEN.length).split("/r/n");   
  11.             request_inst = new HttpRequest();   
  12.             parse(request_inst, headers);   
  13.         }else   return null;    //读取HTTP头不完整,留到下次读取;   
  14.                
  15.     }else { //上次已经读取了HTTP头,本次只读HTTP报文体   
  16.         request_inst = (HttpRequest)request_obj;   
  17.     }   
  18.     String bodylen_str = request_inst.getParam("Content-Length");   
  19.     if (bodylen_str!=null || (! "0".equals(bodylen_str))) {   
  20.            int bodylen_int = Integer.parseInt(bodylen_str);   
  21.            if (buffer.remaining() >= bodylen_int) {   
  22.                byte[] content = new byte[bodylen_int];   
  23.                buffer.get(content);   
  24.                request_inst.setContent(content);   
  25.            } else {   
  26.                return null//等待下次再继续读取   
  27.            }   
  28.        }   
  29. //完整读取了一个HTTP报文(可能BodyLen==0)   
  30. session.removeAttribute(HTTP_HEAD);   
  31. return request_inst;   
  32. }  
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值