voip基础知识 - 数据包的标题信息?

Aub*_*ine 3 java voip udp packets

我学习了在小型网络中使用voip over udp.我知道有一些库准备好了,并且通过一些方法调用来完成我所需要的一切,但正如我所说的我正在学习,所以需要重新发明轮子以了解它是如何工作的.

我目前正在调查DatagramPacket类,我注意到没有方法可以在DatagramPacket类中设置标头信息(即我需要知道的用于交错的包顺序序列号).

一个反映环境的小代码:

byte[] block;
DatagramPacket packet; // UDP packet                

/* x Bytes per block , y blocks per second,
   z ms time block playback duration */

block = recorder.getBlock(); // assume I have class that handles audio
                              // recording and returns speech in a
                              // uncompressed form of bytes

packet = new DatagramPacket(block, block.length, clientIP, PORT);
Run Code Online (Sandbox Code Playgroud)

首先,我假设因为它是UDP,除了他在某处抛出数据包的简单事实之外,发送者并不真正关心任何事情.所以这就是内部没有这种方法的原因.

其次,我假设我需要自己做 - 在要发送的字节块中添加额外的字节,其中包含数据包的序列号?但是我也担心如果我这样做,那么我如何识别字节是字节字节而不是音频字节?我可以假设第一个字节代表一个数字,但我们知道该字节只能代表258个数字.我以前从未在字节级别上工作过.或者可能有其他技术?

简而言之,要做交错,我需要知道如何设置数据包序列号,因为我无法订购无序数据包:-)

谢谢,

nos*_*nos 6

您需要将程序使用的数据类型序列化/反序列化为字节数组.

让我们假设您正在谈论RTP,并且您希望发送包含这些字段的数据包 - 请参阅RTP规范中的第5章:

Version = 2 padding = 0 extension = 0 CSRC count = 1 marker = 0 payload type = 8(G711 alaw)sequence number = 1234 timestamp = 1 one CSRC = 4321

让我们把它们放到一些变量中,使用整数来轻松,或者当我们需要处理无符号的32位值时:

int version = 2;
int padding = 0;
int extension = 0;
int csrcCount = 1;
int marker = 0;
int payloadType = 8;
int sequenceNumber = 1234;
long timestamp = 1;
long ourCsrc = 4321;

byte buf[] = ...; //allocate this big enough to hold the RTP header + audio data

//assemble the first bytes according to the RTP spec (note, the spec marks version as bit 0 and 1, but
//this is really the high bits of the first byte ...
buf[0] = (byte) ((version & 0x3) << 6 | (padding & 0x1) << 5 | (extension & 0x1) << 4 | (csrcCount & 0xf));

//2.byte
buf[1] = (byte)((marker & 0x1) << 7 | payloadType & 0x7f);

//squence number, 2 bytes, in big endian format. So the MSB first, then the LSB.
buf[2] = (byte)((sequenceNumber & 0xff00) >> 8);
buf[3] = (byte)(sequenceNumber  & 0x00ff);

//packet timestamp , 4 bytes in big endian format
buf[4] = (byte)((timestamp & 0xff000000) >> 24);
buf[5] = (byte)((timestamp & 0x00ff0000) >> 16);
buf[6] = (byte)((timestamp & 0x0000ff00) >> 8);
buf[7] = (byte) (timestamp & 0x000000ff);
//our CSRC , 4 bytes in big endian format
buf[ 8] = (byte)((sequenceNumber & 0xff000000) >> 24);
buf[ 9] = (byte)((sequenceNumber & 0x00ff0000) >> 16);
buf[10] = (byte)((sequenceNumber & 0x0000ff00) >> 8);
buf[11] = (byte) (sequenceNumber & 0x000000ff);
Run Code Online (Sandbox Code Playgroud)

这是标题,现在您可以将音频字节复制到buf,从一个数据包开始buf[12]buf作为一个数据包发送.

现在,以上只是为了说明原理,根据RTP规范,RTP数据包的实际串行器必须处理更多(例如,您可能需要一些扩展头,您可能需要多个CSRC,根据您拥有的音频数据的格式,您需要正确的有效载荷类型,您需要打包并正确安排这些音频数据 - 例如,对于G.711Alaw,您应该用160字节的音频数据填充每个RTP数据包并发送一个数据包每20毫秒.