InputStream读取源

时间:2016-03-24 18:53:36

标签: java sockets stream byte inputstream


我有Java服务器接收从客户端应用程序发送的RTMP数据包。服务器使用packet header读取InputStream,识别packet body有多大,然后使用byte array创建size,然后读取body来自InputStream的{​​{1}} 问题是:收到的字节数是已修改 - 有必要的字节(存在于源中),其中包含源中不存在的额外字节数据包(我通过WireShark观察源数据包的内容,并将它们与我在服务器上收到的那些字节进行比较)。
这些额外的字节是array字节,通过这种方式周期性地相遇...
它看起来像这样:
0xc6
Source: ... 75 f1 f5 55 73 .... fc a9 47 14 ... 40 ca d5 75 ... fe 30 a7
Received: ... 75 f1 f5 55 73 c6 .... fc a9 47 14 c6 ... 40 ca d5 75 c6 ... fe 30 a7 - 表示"此处有一定数量的字节"
因此,我无法收到必要的数据,因为它比我从rtmp ...收到的body size更加拉伸,比它更大。 。最重要的是,修改后的数据不是我必须收到的! 我的问题是:如何修复? header有什么问题?为什么它会将这些InputStream字节插入接收数组? 我知道我可以简单地解析收到的数组并排除那些额外的字节,但这是不好的解决方案,因为速度和性能是必要的(在这种情况下,它不清楚它是一个额外的字节或来自源的字节,没有整个数组的比较)...

0xc6

4 个答案:

答案 0 :(得分:2)

根据RTMP规范,它表现正常。您需要“取消”传入数据,因此在单个read()中一次读取所有数据将无法正常工作。

沿着这些方向的东西(伪代码):

int remaining = payloadSize;
int totalRead = 0;
int totalReadForChunk = 0;
while (true) {
  int num = read(buf, 0, min(remaining, chunkSize - totalReadForChunk))
  if (num < 0) break;  // i/o error
  appendData(<buf>, 0, num)
  totalReadForChunk += num
  remaining -= num
  if (remaining == 0) break;  // end of payload

  if (totalReadForChunk == chunkSize) {
     totalReadForChunk = 0;
     // read the chunk header (it's not neccessarily 0xc6)
     int header = read()
     if (header != currentStreamEmptyHeader) {  // 0xc6
       // ... parse the new rtmp message according to header value
       // (usually invoke the upper-level message reading method "recursively")
     }
  }
}

答案 1 :(得分:0)

您可能应该看到(并使用)Red5 Media Server和其他实现RTMP协议的开源解决方案的代码。

答案 2 :(得分:0)

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.

答案 3 :(得分:0)

问题得到解决 那些额外的<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Example - example-guide-concepts-1-production</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> </head> <body ng-app="myApp"> <div ng-app ng-controller="selectCtrl"> <div class=select> <select ng-model="value" class="ghostSelect"> <option value="Option 1">Option 1</option> <option value="Option 2">Option 2</option> <option value="Option 3">Option 3</option> </select> <div>{{value}} </div> </div> </div> </body>字节是RTMP数据包的分块字节,从WireShark中看不到。
不仅如此,收到的标题显示实际的身体尺寸和WireShark“确认”它,但实际上身体尺寸会更大,应该计算。