这里只讨论如何实践,不涉及为什么这么设计
basic由两部分组成,分别是:fmt和csid,其中:
- fmt决定了后面MessageHeader的格式,
- csid表示一个媒体流通道,( notice:不是一个流,对相同流的推拉一般而言是不同的csid)
下面的代码很好的展示了如何解析basic header的内容,结合代码和rfc,可以更好的理解解析过程。
public class BasicHeader {
@Getter
private int fmt;
@Getter
private int csid;
@Getter
private int byteLength;
public BasicHeader(byte[] buffer) {
byteLength = decode(buffer);
}
private int decode(byte[] buffer) {
int headerLength = 1;
fmt = (buffer[0] & 0xff) >> 6;
csid = (buffer[0] & 0x3f);
if (csid == 0) {
// 2 byte form
csid = buffer[1] & 0xff + 64;
headerLength += 1;
} else if (csid == 1) {
// 3 byte form
this.csid = (buffer[2] & 0xff) << 8 + (buffer[1] & 0xff) + 64;
headerLength += 2;
}
return headerLength;
}
}
不同长度的basic header
解析之前需要先做一个假设,假设Basic Header是一个字节的长度,如图:
这里csid理论取值是从0-63,但是rfc规定,0,1,2是保留项。
-
如果我们解析出来是3-63,那么这个就是真实的csid,并且这也是basic header的全部内容。
-
如果我们解析出来csid = 0,那么实际的Basic Header其实是这个样子的。
占两个字节的长度,这里第二个字节就是真实的csid。为什么标准文档上要减掉64呢?这是因为图中的csid表示的是6 + 8字节的内容,减去64相当于向右平移6个bit,正好就是第二个字节的内容。 -
如果我们解析出来的csid = 1,那么实际上的Basic Header其实是这个样子的。
占三个字节长度,这里的第二第三个字节就是真实的csid。这里减去64和csid=0的情况是一样的。 -
最后如果我们解析出来的csid=2,按照rfc的解释:Chunk Stream ID with value 2 is reserved for low-level protocol control messages and commands.
这个是一个预留给底层控制协议的。