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;
}
}