1.問題描述
在wkt模擬器上, 通過以下代碼可以正確的讀出數(shù)據(jù):
conn = (SocketConnection) Connector.open(url, Connector.READ_WRITE, true);
is = conn.openDataInputStream();
os = conn.openDataOutputStream();
// 創(chuàng)建登陸報(bào)文
loginPacketBytes = generateLoginPacket();
// 發(fā)送登陸報(bào)文
// System.out.println("****發(fā)送登陸報(bào)文****");
os.write(loginPacketBytes, 0, loginPacketBytes.length);
os.flush();
// 先讀取ConstantValue.HEADER_LENGTH個字節(jié),循環(huán)遍歷尋找正確的魔數(shù)
recByteNum = is.read(recBytes, 0, ConstantValue.READ_LENGTH);
若從服務(wù)器真是返回的字節(jié)數(shù)是100個字節(jié), 而ConstantValue.READ_LENGTH定義的長度大于100.
那么在模擬器上沒有問題, 能夠讀到100個字節(jié).
但是到了真機(jī)上面測試, 若定義的要讀取的字節(jié)數(shù)大于實(shí)際傳送的字節(jié)數(shù), 那就會出現(xiàn)異常情況.
導(dǎo)致根本就讀不到數(shù)據(jù).
2.解決方法
先讀取一小部分?jǐn)?shù)據(jù), 得到報(bào)文頭(一般都有報(bào)文頭, 報(bào)文頭中都有整個報(bào)文的總長度)
解析報(bào)文頭, 這里需要注意的是可能收到的第一個數(shù)據(jù)并不就是報(bào)文的有效數(shù)據(jù), 報(bào)文的有效數(shù)據(jù)可能并不在數(shù)據(jù)緩沖區(qū)的首位置, 所以需要正確找到報(bào)文頭, 方法各不相同, 有的是使用魔數(shù)這種方式, 有個就靠判斷某個值是否等于報(bào)文的總長度. 總之記住有效報(bào)文的開始位置, 這里記著index,
然后創(chuàng)建一個字節(jié)緩沖區(qū), 剛好來接受剩余的數(shù)據(jù)
byte addBytes[] = new byte[recHeader.getBufferSize() + index - (recByteNum - ConstantValue.HEADER_LENGTH)];
is.readFully(addBytes);這樣一般就可以正確的讀出有效數(shù)據(jù)了.
3.最新方法 int loop = 0;
int hasReadLen = 0;
// 讀取報(bào)文頭
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)
{
// 讀取報(bào)文頭
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)
{
// 解析報(bào)文總長度
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);
}
// 讀取報(bào)文體
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;
}
// 讀取剩余數(shù)據(jù)
recByteNum = m_oCfgIs.read(m_byCfgRecBuf, hasReadLen, pakcetTotalLen - hasReadLen);
hasReadLen += recByteNum;
// 讀取完畢
if (hasReadLen >= pakcetTotalLen)
{
break;
}
else
{
Thread.sleep(100);
continue;
}
}