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()
      中,他打算输入整个消息