我已经阅读了很多有关java InputStream和读取数据的教程和帖子。我已经建立了一个客户端和服务器实现,但我有一些奇怪的问题,其中读取可变长度"有效载荷"来自客户的不一致。
我想要做的是在一个逻辑有效负载中传输最大100kB。现在我已经验证TCP堆栈没有从客户端发送一个mahousive 100kB数据包。我根据之前关于InputStream读数的问题玩了不同的阅读形式,但我几乎试图让我的头发试图让它转储正确的数据。
比如说让客户端发送70k的有效载荷。
现在我注意到的第一个观察是,如果我从一个断点开始逐行流过代码,它将正常工作,我在出站字节[]中获得完全相同的计数。当自由运行时,每次运行具有几乎相同负载的代码时,byte []的大小都会不同。
时间问题?
第二个观察是当" inbuffer" size设置为4096,例如发生这种奇怪的行为。设置" inbuffer" size to 1表示正确的行为,即我得到正确的有效载荷大小。请理解我不喜欢我必须让这个工作的方式,我对解决方案不满意。
您分别遇到过哪些经验,问题可能有助于我修复此代码,使其更可靠,更易于阅读。
public void listenForResponses() {
isActive = true;
try {
// apprently read() doesnt return -1 on socket based streams
// if big stuff comes through, TCP packets are segmented, but the inputstream
// does something odd and doesnt return the correct raw data.
// this is a work around to accept vari-length payloads into one byte[] buffer
byte[] inBuffer = new byte[1];
byte[] buffer = null;
int bytesRead = 0;
byte[] finalbuffer = new byte[0];
boolean isMultichunk = false;
InputStream istrm = currentSession.getInputStream();
while ((bytesRead = istrm.read(inBuffer)) > -1 && isActive) {
buffer = new byte[bytesRead];
buffer = Arrays.copyOfRange(inBuffer, 0, bytesRead);
int available = istrm.available();
if(available < 1) {
if(!isMultichunk) {
finalbuffer = buffer;
}
else {
finalbuffer = ConcatTools.ByteArrayConcat(finalbuffer,buffer);
}
notifyOfResponse(deserializePayload(finalbuffer));
finalbuffer = new byte[0];
isMultichunk = false;
}
else {
if(!isMultichunk) {
isMultichunk = true;
finalbuffer = new byte[0];
}
finalbuffer = ConcatTools.ByteArrayConcat(finalbuffer,buffer);
}
}
} catch (IOException e) {
Logger.consoleOut("PayloadReadThread: " + e.getMessage());
currentSession = null;
}
}
答案 0 :(得分:0)
InputStream
按设计工作。
如果我从断点开始逐行流过代码,它将正常工作,我在出站字节[]中获得完全相同的计数。
这是因为逐步执行代码的速度较慢,因此读取之间的数据驱动量会增加,足以填满缓冲区。
当自由运行时,每次运行具有几乎相同负载的代码时,byte []的大小都会不同。
这是因为InputStream.read()
被约束为阻塞,直到至少传输了一个字节,或者发生了EOS或异常。见Javadoc。填充缓冲区没有任何内容。
第二个观察是,当“inbuffer”大小设置为4096时,例如发生这种奇怪的行为。将“inbuffer”大小设置为1表示正确的行为,即我得到正确的有效负载大小。
对于1字节缓冲区,这是正确的行为,原因与上面给出的完全相同。这不是任何其他尺寸的'正确行为'。
注意你的复制循环是胡说八道。 availavle()
几乎没有正确的用途,这不是其中之一。
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
NB(2)read()
确实在基于套接字的流上返回-1,但仅在对等方关闭或关闭连接时才返回。