Java InputStream读取源中不存在的额外字节
Java InputStream读取源中不存在的额外字节,java,sockets,stream,byte,inputstream,Java,Sockets,Stream,Byte,Inputstream,我有一个Java服务器,它接收从客户端应用程序发送的RTMP数据包。服务器使用InputStream读取数据包头,识别数据包正文有多大,然后用该大小创建字节数组,然后从该数组中的InputStream读取该正文 问题是:收到的字节集被修改了-有必要的字节(存在于源代码中)与源数据包中不存在的额外字节(我通过WireShark查看源数据包的内容,并将它们与我在服务器上收到的字节进行比较)。 这些额外的字节是0xc6字节,它们会定期相遇… 看起来是这样的: 来源:。。。75 f1 f5 55 73。
我有一个Java服务器,它接收从客户端应用程序发送的RTMP数据包。服务器使用
InputStream
读取数据包头
,识别数据包正文
有多大,然后用该大小创建字节数组
,然后从该数组中的InputStream
读取该正文
问题是:收到的字节集被修改了-有必要的字节(存在于源代码中)与源数据包中不存在的额外字节(我通过WireShark查看源数据包的内容,并将它们与我在服务器上收到的字节进行比较)。
这些额外的字节是0xc6
字节,它们会定期相遇…
看起来是这样的:
来源:。。。75 f1 f5 55 73。。。。fc a9 47 14。。。40卡d5 75。。。fe 30 a7
收到:。。。75 f1 f5 55 73 c6。。。。fc a9 47 14 c6。。。40卡d5 75 c6。。。fe 30 a7
…
-表示“此处有一定数量的字节”
因此,我无法接收必要的数据,因为它被拉伸了,比我从rtmp标题接收到的正文大小要大。最重要的是,修改后的数据不是我必须接收的
我的问题是:如何修复?InputStream
有什么问题?为什么要将这些0xc6
字节插入接收阵列?
我知道我可以简单地解析接收到的数组并排除这些额外的字节,但这是一个糟糕的解决方案,因为速度和性能是必需的(在这种情况下,不清楚它是一个额外的字节还是来自源的字节,而不比较整个数组)
可能,您应该看到(并使用)Red5 Media Server和其他实现RTMP协议的开源解决方案的代码。可能,您应该看到(并使用)Red5 Media Server和其他实现RTMP协议的开源解决方案的代码。InputStream.read(byte[])只保证读取一个字节,它返回实际读取长度的int
in.read(rtmpHeader); // might read 1, 2, 3, .. 8 bytes.
//reading the body size. This method works fine
bodySize = Server.bigEndianBytesToInt(rtmpHeader, 4, 3);
rtmpBody = new byte[bodySize];
in.read(rtmpBody); // might read 1, 2, 3, ... bodySize bytes.
如果不检查实际长度,并假设字节[]已满,则在调用read()之前会得到任何字节
使用DataInputStream可以获得您想要的内容
DataInputStream dis = new DataInputStream(in);
int len = dis.readInt(); // read an int in big endian.
byte[]] bytes = new byte[len];
dis.readFully(bytes); // read the whole byte[] or throw an IOException.
InputStream.read(byte[])只保证读取一个字节,它返回的长度为实际读取长度的int
in.read(rtmpHeader); // might read 1, 2, 3, .. 8 bytes.
//reading the body size. This method works fine
bodySize = Server.bigEndianBytesToInt(rtmpHeader, 4, 3);
rtmpBody = new byte[bodySize];
in.read(rtmpBody); // might read 1, 2, 3, ... bodySize bytes.
如果不检查实际长度,并假设字节[]已满,则在调用read()之前会得到任何字节
使用DataInputStream可以获得您想要的内容
DataInputStream dis = new DataInputStream(in);
int len = dis.readInt(); // read an int in big endian.
byte[]] bytes = new byte[len];
dis.readFully(bytes); // read the whole byte[] or throw an IOException.
问题解决了。
那些额外的0xc6
字节是RTMP数据包的分块字节,在WireShark中不可见。
除此之外,收到的标题说,实际的身体大小和WireShark“确认”它,但事实上身体大小将更大,应该计算
问题已经解决。
那些额外的
0xc6
字节是RTMP数据包的分块字节,在WireShark中不可见。
除此之外,收到的标题说,实际的身体大小和WireShark“确认”它,但事实上身体大小将更大,应该计算
根据RTMP规范,其行为正常。您需要“取消锁定”传入数据,因此在一次读取()中一次性读取所有数据将不起作用
大致如下(伪代码):
int剩余=有效负载大小;
int totalRead=0;
int totalReadForChunk=0;
while(true){
int num=read(buf,0,min(剩余,chunkSize-totalReadForChunk))
如果(num<0)中断;//i/o错误
追加数据(,0,num)
totalReadForChunk+=num
剩余-=num
如果(剩余==0)中断;//有效负载结束
if(totalReadForChunk==chunkSize){
totalReadForChunk=0;
//读取区块头(不一定是0xc6)
int header=read()
如果(标头!=CurrentStreamMPtyHeader){//0xc6
//…根据标头值解析新rtmp消息
//(通常“递归地”调用上层消息读取方法)
}
}
}
根据RTMP规范,它的行为正常。您需要“取消锁定”传入数据,因此在一次读取()中一次性读取所有数据将不起作用
大致如下(伪代码):
int剩余=有效负载大小;
int totalRead=0;
int totalReadForChunk=0;
while(true){
int num=read(buf,0,min(剩余,chunkSize-totalReadForChunk))
如果(num<0)中断;//i/o错误
追加数据(,0,num)
totalReadForChunk+=num
剩余-=num
如果(剩余==0)中断;//有效负载结束
if(totalReadForChunk==chunkSize){
totalReadForChunk=0;
//读取区块头(不一定是0xc6)
int header=read()
如果(标头!=CurrentStreamMPtyHeader){//0xc6
//…根据标头值解析新rtmp消息
//(通常“递归地”调用上层消息读取方法)
}
}
}
code,谢谢。最好简化为。InputStream
不会这样做。如果确实如此,那就意味着消息来源没有你想象的那么有约束力。这是不可信的。显然,您在未发布的代码中有bug,例如bytesToString()
。请输入代码。最好简化为。InputStream
不会这样做。如果确实如此,那就意味着消息来源没有你想象的那么有约束力。这是不可信的。显然,你没有发布的代码中有bug,比如bytesToString()
。你写的一切都是正确的,但这似乎并不能解释OP的关键主张和担忧:在他的单条read()
中,他打算输入整个消息