随笔 - 2, 文章 - 73, 评论 - 60, 引用 - 0
数据加载中……

J2ME中Socket如何正确读取缓冲区中的数据

1.问题描述

在wkt模拟器上, 通过以下代码可以正确的读出数据:
 
 conn = (SocketConnection) Connector.open(url, Connector.READ_WRITE, true);
  
  is = conn.openDataInputStream();
  os = conn.openDataOutputStream();
  // 创建登陆报文
  loginPacketBytes = generateLoginPacket();
 
  // 发送登陆报文
  // System.out.println("****发送登陆报文****");
  os.write(loginPacketBytes, 0, loginPacketBytes.length);
  os.flush();
 
  // 先读取ConstantValue.HEADER_LENGTH个字节,循环遍历寻找正确的魔数
  recByteNum = is.read(recBytes, 0, ConstantValue.READ_LENGTH);


若从服务器真是返回的字节数是100个字节, 而ConstantValue.READ_LENGTH定义的长度大于100.
 那么在模拟器上没有问题, 能够读到100个字节.

但是到了真机上面测试, 若定义的要读取的字节数大于实际传送的字节数, 那就会出现异常情况.

导致根本就读不到数据.

2.解决方法

先读取一小部分数据, 得到报文头(一般都有报文头, 报文头中都有整个报文的总长度)
解析报文头, 这里需要注意的是可能收到的第一个数据并不就是报文的有效数据, 报文的有效数据可能并不在数据缓冲区的首位置, 所以需要正确找到报文头, 方法各不相同, 有的是使用魔数这种方式, 有个就靠判断某个值是否等于报文的总长度. 总之记住有效报文的开始位置, 这里记着index,
然后创建一个字节缓冲区, 刚好来接受剩余的数据
byte addBytes[] = new byte[recHeader.getBufferSize() + index - (recByteNum - ConstantValue.HEADER_LENGTH)];
is.readFully(addBytes);

这样一般就可以正确的读出有效数据了.

3.最新方法
   int loop = 0;
   int hasReadLen = 0;
   
   // 读取报文头
   while (true)
   {
    loop++;
    
    if (loop >= m_oNET_DVR.m_iTimeOutVal / NET_DVR_PARAM.LOOP_INTERVAL)
    {
     SDK.SetLastError(NET_DVR_Dec.NET_DVR_NETWORK_RECV_TIMEOUT);
     return NET_DVR_Dec.RET_FAIL;
    }
     
    if (m_oCfgIs.available() >= NET_DVR_PARAM.REC_PACKET_HEADER_LENGTH)
    {
     // 读取报文头
     recByteNum = m_oCfgIs.read(m_byCfgRecBuf, 0, NET_DVR_PARAM.REC_PACKET_HEADER_LENGTH);
     
     hasReadLen += recByteNum;
     
     if (recByteNum == NET_DVR_PARAM.REC_PACKET_HEADER_LENGTH)
     {
      // 解析报文总长度
      pakcetTotalLen  = NetHelper.convertNetBytesToInt(m_byCfgRecBuf, 0);
      break;
     }
     else
     {
      SDK.SetLastError(NET_DVR_Dec.NET_DVR_NETWORK_RECV_ERROR);
      return NET_DVR_Dec.RET_FAIL;
     }
    }
    
    Thread.sleep(NET_DVR_PARAM.LOOP_INTERVAL);
   }
   
   // 读取报文体
   while (true)
   {
    loop++;
    
    if (loop >= m_oNET_DVR.m_iTimeOutVal / NET_DVR_PARAM.LOOP_INTERVAL)
    {
     SDK.SetLastError(NET_DVR_Dec.NET_DVR_NETWORK_RECV_TIMEOUT);
     return NET_DVR_Dec.RET_FAIL;
    }
    
    // 读取剩余数据
    recByteNum = m_oCfgIs.read(m_byCfgRecBuf, hasReadLen, pakcetTotalLen - hasReadLen);
    
    hasReadLen += recByteNum;
    
    // 读取完毕
    if (hasReadLen >= pakcetTotalLen)
    {
     break;
    }
    else
    {
     Thread.sleep(100);
     continue;
    }
   }

posted on 2009-04-16 09:34 郭天文 阅读(1495) 评论(0)  编辑 收藏 引用 所属分类: J2ME


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理