最近由于自己在B站直播的原因,对B站本身提供的实时弹幕不太满意,于是自己抓包写了一个bilibili的弹幕协议,但还有一部分没有完成。留下的坑以后再慢慢填吧。
socket包获拦截工具:Wireshark
demo实现语言环境:C#
抓取过程
1、获取直播间的ROOM_ID
bilibili的直播房间的URL是形如:http://live.bilibili.com/180 类型的
但和其他直播网站不同的是180是临时分配的房间号
查看网页源码,在头文件中可以找到:
- <head>
- <!-- 省略 -->
- <script>
- var ROOMID = 98284;
- var DANMU_RND = 1479304877;
- var NEED_VIDEO = 1;
- var ROOMURL = 180;
- var INITTIME = Date.now();
- </script>
- <!-- 省略 -->
- </head>
获取对应:
ROOMID位真实房间号
DANMU_RND推测应该是用户登录的分配随机数
2、wireshark解析
通过简单的网页流量监控能够找出bilibili弹幕服务器的IP地址
可以看出目标主机的IP是:183.147.212.11 端口号为788
紧接着使用wirshark抓包
设置拦截条件为
tcp.port==788 && ip.addr==183.147.212.11
进入直播间分析数据:
PSH,ACK 端口为788
解析数据
- 0000 00 00 00 3d 00 10 00 01 00 00 00 07 00 00 00 01 ...=............
- 0010 7b 22 72 6f 6f 6d 69 64 22 3a 31 31 38 32 37 35 {"roomid":118275
- 0020 36 2c 22 75 69 64 22 3a 37 36 39 34 32 36 32 2c 6,"uid":7694262,
- 0030 22 70 72 6f 74 6f 76 65 72 22 3a 32 7d "protover":2}
0x3d 数据长度
0x07 进入直播间
后面一部分按照正常方式解析为就可以
心跳包解析:
由于采用TCP/IP协议,通过wireshark发现每隔一段时间都会固定向183.147.212.11 788 发送一个固定大小为70的封包
取出其中data部分
- 0000 00 00 00 10 00 10 00 01 00 00 00 02 00 00 00 01 ................
紧接着解析收到的心跳内容
- 0000 00 00 00 14 00 10 00 01 00 00 00 03 00 00 00 01 ................
- 0010 00 00 00 03 ....
第一个0x03是心跳标志
最后的 0x0003 是当前房间的人数
弹幕数据:
每当有数据来的时候
很容易解析
- 0000 00 00 00 b9 00 10 00 00 00 00 00 05 00 00 00 00 ................
- 0010 7b 22 69 6e 66 6f 22 3a 5b 5b 30 2c 31 2c 32 35 {"info":[[0,1,25
- 0020 2c 31 36 37 37 37 32 31 35 2c 31 34 37 39 33 30 ,16777215,147930
- 0030 37 39 30 35 2c 2d 32 37 39 30 33 35 33 39 36 2c 7905,-279035396,
- 0040 30 2c 22 39 37 64 37 65 34 31 38 22 2c 30 5d 2c 0,"97d7e418",0],
- 0050 22 73 73 73 73 22 2c 5b 37 36 39 34 32 36 32 2c "ssss",[7694262,
- 0060 22 e8 bd af e8 82 9a e5 ad 90 e7 9a 84 e7 8b 90 "...............
- 0070 e7 8b b8 22 2c 31 2c 31 2c 30 2c 31 30 30 30 30 ...",1,1,0,10000
- 0080 2c 31 5d 2c 5b 5d 2c 5b 32 30 2c 30 2c 36 32 31 ,1],[],[20,0,621
- 0090 35 36 37 39 2c 22 3e 35 30 30 30 30 22 5d 2c 5b 5679,">50000"],[
- 00a0 5d 2c 30 2c 30 5d 2c 22 63 6d 64 22 3a 22 44 41 ],0,0],"cmd":"DA
- 00b0 4e 4d 55 5f 4d 53 47 22 7d NMU_MSG"}
其中的内容分析:
0,1,25标准格式不清楚
16777215为当前登录ID
1479307905为前方分析的DANMU_RND
“97d7e418”不清楚
"ssss"为弹幕内容
7694262为用户ID
“...”没能显示的为用户姓名
1,1,0分别对应 admin,vip,svip
后面的内容没有做分析
这里给出我分析出来的弹幕命令
- {"info":[[0,1,25,16777215,1478145019,1098959490,0,"73dec35f",0],"初二物理",[11911154,"Asysika",0,0,0,10000],[],[2,0,16754085,">50000"],[],0,0],"cmd":"DANMU_MSG"}
- {"cmd":"WELCOME","data":{"uid":3966619,"uname":"\u5c0f\u68a6\u306e\u7ae0\u9c7c\u54e5","isadmin":1,"svip":1}
- {"cmd":"SEND_GIFT","data":{"giftName":"233","num":1,"uname":"\u5c0f\u68a6\u306e\u7ae0\u9c7c\u54e5","rcost":121841,"uid":3966619,"top_list":[{"uid":3966619,"uname":"\u5c0f\u68a6\u306e\u7ae0\u9c7c\u54e5","coin":1440977,"guard_level":0}
- {"uid":3966619,"uname":"\u5c0f\u68a6\u306e\u7ae0\u9c7c\u54e5","coin":1440045,"guard_level":0}
- {"info":[[0,1,25,16777215,1478149142,2130510810,0,"8f533746",0],"下播了吗",[24614852,"溟孜沐",0,0,0,10000],[3,"梦宝","阿梦小盆友",1275151,7722635],[18,0,6215679,">50000"],["title-56-1","title-56-1"],0,0],"cmd":"DANMU_MSG"}
- {"cmd":"SYS_MSG","msg":"\u3010\u821e\u6cd5\u5929\u5973\u75f4\u6c49\u5f03\u3011:?\u5728\u76f4\u64ad\u95f4:?\u3010187\u3011:?\u8d60\u9001 \u5c0f\u7535\u89c6\u4e00\u4e2a\uff0c\u8bf7\u524d\u5f80\u62bd\u5956","rep":1,"styleType":2,"url":"http:\/U_MSG"}
其中的TCP封包存在被分割的情况,读取的话socket不要设置为拥塞模式
在这里做了一个小的demo演示,支持弹幕点歌,但是还没有完善,有兴趣的同学可以帮我把坑填上
结语
因为自身的局限,任然有一部分的信息没有分析出来,也希望有志同道合的朋友一起把弹幕协议完善。