我有一个TCP套接字客户端,它从服务器接收消息(数据)。消息的类型为长度(2个字节)+数据(长度字节),由STX和ETX字符分隔。
我正在使用bufferedReader来检索前两个字节,对长度进行解码,然后再次从同一bufferedReader中读取适当的长度,并将结果放入char数组中。
在大多数情况下,我都没问题,但是有时(收到的数千条消息中有1条),当尝试从读取器读取(长度)字节时,我只得到其中的一部分,其余的数组都用“ NUL”字符。我想这是因为缓冲区尚未填充。
char[] bufLen = new char[2]; _bufferedReader.read(bufLen); int len = decodeLength(bufLen); char[] _rawMsg = new char[len]; _bufferedReader.read(_rawMsg); return _rawMsg;
我以几种迭代的方式解决了这个问题:
首先,我测试了数组的最后一个字符:如果不是ETX,我将一个一个地从bufferedReader读取字符,直到到达ETX,然后从常规例程开始。结果是我基本上会丢弃一条消息。
然后,为了仍然检索该消息,我将在我的“截断”消息中找到NUL字符的第一次出现,一次读取并存储其他字符,直到到达ETX,然后将它们附加到我的“截断”消息中,确认长度可以。
它也可以工作,但是我真的在想我可以做得更好,例如在读取缓冲区之前检查缓冲区中是否有我需要的字符总数,但是找不到正确的方法…
有什么想法/指针吗?
谢谢 !
InputStream读取方法可能返回短读取;您必须检查返回值以确定已读取的字符数,并继续循环读取直到获得所需的数字。该方法可能会阻塞,但是只会阻塞直到 某些 数据可用(不一定是您请求的所有数据)可用为止。
大多数人最终都会编写一个“ readFully”方法,例如DataInputStream,该方法读取预期的数据量或引发IOException:
static public int readFully(InputStream inp, byte[] arr, int ofs, int len) throws IOException { int rmn,cnt; for(rmn=len; rmn>0; ofs+=cnt, rmn-=cnt) { if((cnt=inp.read(arr,ofs,rmn))==-1) { throw new IOException("End of stream encountered before reading at least "+len+" bytes from input stream"); } } return len; }