rtmp握手过程

来源:互联网 发布:8888端口干嘛的 编辑:程序博客网 时间:2024/06/08 03:55

rtmp通信以握手开始,即客户端与服务端相互发消息块。其中客户端发送的消息块被指定为C0,C1,C2,服务端发送的消息块指定为S1,S2,S3。

握手顺序

1.客户端主动发送C0,C1;客户端必须等待S1到达才能发送C2;必须等待S2到达才能发送其他数据;

2.服务端必须等待C0到达才能发送S0和S1;必须等待C1到达才能发送S2;必须等待C2到达才能发送其他数据;

C0和S0格式

1.长度:1字节

2.C0表示客户端需求的rtmp版本;S0表示服务端选择的rtmp版本。目前版本为3,0到2是之前使用的版本,4到31保留,32到255被禁用。

C1和S1

1.长度:1536字节,其中包含以下字段。

  • 时间戳(4字节)

  • 0标示(4字节)

  • 随机字段(1528字节),用于区分握手的返回数据;

C2和S2

1.长度:1536字节,相当于的C1和S1的返回数据,包含数据如下:

  • 时间戳(4字节),对于C2来说是指发送C1的时间戳;对于S2来说是指发送S1的时间戳;

  • 时间戳(4字节),对于C2来说是指读到S1中的时间戳;对于S2来说是指读到C2中的时间戳;

  • 随机字段(1528字节),对于C2来说是指读到S1中的随机字段;对于S2来说是指读到C2中的随机字段;

rtmpdump中握手过程的实现

握手过程的具体实现在handshake.h文件中,这里仅仅讲诉握手过程,而忽略其他细节部分。在HandShake函数中大部分都是加密部分的代码,与握手主流程关系不大。

static int HandShake(RTMP * r, int FP9HandShake){//1.其将C0和C1作为一个整体一起发送,clientbuf的长度为1540(RTMP_SIG_SIZE为1536),而clientsig指向C1。uint8_t clientbuf[RTMP_SIG_SIZE + 4], *clientsig=clientbuf+4;uint8_t serversig[RTMP_SIG_SIZE], client2[RTMP_SIG_SIZE], *reply;//2.对于C0的赋值,clientsig为指向C1的指针,而clientsig减去1指向C0。clientsig[-1] = 0x03;//3. C1的时间戳uptime = htonl(RTMP_GetTime());memcpy(clientsig, &uptime, 4);//4. C1的零标示memset(&clientsig[4], 0, 4);//5. C1的随机数,在调试模式下直接赋值为0/* generate random data */#ifdef _DEBUGmemset(clientsig+8, 0, RTMP_SIG_SIZE-8);#elseip = (int32_t *)(clientsig+8);for (i = 2; i < RTMP_SIG_SIZE/4; i++)        *ip++ = rand();#endif//6.发送C0和C1,读取S0if (!WriteN(r, (char *)clientsig-1, RTMP_SIG_SIZE + 1))        return FALSE;if (ReadN(r, (char *)&type, 1) != 1)/* 0x03 or 0x06 */        return FALSE;//7.判断S0是否正确if (type != clientsig[-1])//8.接受S1if (ReadN(r, (char *)serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)        return FALSE;//9.赋值S1的时间戳memcpy(&uptime, serversig, 4);uptime = ntohl(uptime);//10.reply = serversig;//11.发送C2if (!WriteN(r, (char *)reply, RTMP_SIG_SIZE))        return FALSE;//12.读取S2/* 2nd part of handshake */if (ReadN(r, (char *)serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)          return FALSE;//13.对比随机数if (memcmp(serversig, clientsig, RTMP_SIG_SIZE) != 0)}
0 0