斗鱼弹幕的获取 ,有C++源码,能否帮忙转一下VB的。

jiaxueq 2017-09-06 05:30:38
斗鱼已开放API,也有fans做了DEMO发在网上了, C++的,易语言的,Python的。

(叹一下,可惜没有VB版的DEMO,哪怕 vb.net 的也好啊,至少能看个大概)


C++源码: http://pan.baidu.com/s/1nuYjSTz 密码: txv5

看了下代码也不是很长,握手和接收处理消息douyutcpsocket.cpp,stringgenerator.cpp,好像有百多行代码吧。

就会一点VB,确实不会C++,希望大神能把关键的部份转成VB一下,谢过。
...全文
3311 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
橘子皮... 2017-09-12
  • 打赏
  • 举报
回复
感觉获取弹幕没什么用啊,要是能发弹幕就有用了
橘子皮... 2017-09-12
  • 打赏
  • 举报
回复
引用 26 楼 jiaxueq 的回复:
先纠正下上面的字误,是12byte不是12bit。 感觉和之前用数组收集的情况一样 (只是用Collection对象要好些了) 在百W人气的ID,跑着跑着,时间久了还是产生了 字节与长度的误差。
发下完整代码吧,学习学习
jiaxueq 2017-09-11
  • 打赏
  • 举报
回复
先纠正下上面的字误,是12byte不是12bit。 感觉和之前用数组收集的情况一样 (只是用Collection对象要好些了) 在百W人气的ID,跑着跑着,时间久了还是产生了 字节与长度的误差。
jiaxueq 2017-09-11
  • 打赏
  • 举报
回复
打脸了,真是夸不得。刚回了贴,想再观察下,没多久就报这个



好像是coll已经没数据了,这里还访问coll(1),郁闷

jiaxueq 2017-09-10
  • 打赏
  • 举报
回复
引用 23 楼 Runnerchin 的回复:
不是一个叫Collection的Byte数组,是Collection对象。
谢谢Runnerchin大神,用Collection后,貌似更简单了。 到百万人房间运行1小时也没问题了。

    Dim msgBytes() As Byte
    Dim k As Long
    ReDim msgBytes(bytesTotal - 1)
    Winsock1.GetData msgBytes
    
    '--- 串接包
    For k = 0 To bytesTotal - 1
        coll.Add msgBytes(k)
        LenCurMsg = LenCurMsg + 1
    Next

    Do While (LenCurMsg > 12)    '读完整个串接包。 一个完整包至少>12bit
        '--- 取临界第1条包长指定的数据
        Dim packSize As Long, tmpMsgBytes() As Byte
        Dim tmpMsg As String
        packSize = coll(4) * 256 ^ 3 + coll(3) * 256 ^ 2 + coll(2) * 256 + coll(1)
        If packSize > LenCurMsg Then
            WriteLog ("!数据不够包头指定的长度,继续串接下一包")
            Exit Sub
        End If
    
        '--- 读第1个 删第1个。
        ReDim tmpMsgBytes(packSize + 4 - 1)
        For k = 0 To packSize + 4 - 1
            If k > 11 Then   '除开包头信息 前12bit (0-11)
                tmpMsgBytes(k - 12) = coll(1)
            End If
            coll.Remove 1
            LenCurMsg = LenCurMsg - 1
        Next
        
        '--- 转码
        tmpMsg = DecodeToBytes(tmpMsgBytes)
        WriteLog ("串包剩余大小" & LenCurMsg & " , 本条消息大小" & k & ", 内容:" & tmpMsg)

        ’DoEvents ‘这里时间久了,会出现堆栈溢出,不解!!!不过影响不大。暂时用resume next解决
    Loop
再次感谢 Runnerchin
X-i-n 2017-09-10
  • 打赏
  • 举报
回复
不是一个叫Collection的Byte数组,是Collection对象。对数组操作时,如果频率够快的话,有可能去除头部的动作和追加的动作同时发生,导致冲突,这样数据就错乱了,正常讲这地方应该用锁。用Collection能保证你去除头部的动作和追加的动作同时发生的时候也不会有冲突。
X-i-n 2017-09-09
  • 打赏
  • 举报
回复
建一个全局的Collection,比如叫coll。全局int变量LenCurMsg=0 Winsock_dataarrival的时候,不着急解析,先获取所有内容,再一个字节一个字节续到coll。 从收到第一批数据开始(第一批数据的开头一定也是第一条弹幕消息的开头): 1. LenCurMsg=0说明是第一次接收数据,读出当前这条消息的长度并保存变量 2. 接收并填充coll 3. 判断coll有没有达到LenCurMsg+8,达到了(也可能是大于,不会每次都刚好)就说明当前这条消息就收全了,进入解包流程 3.1 coll的前LenCurMsg个元素就是一条完整的消息,读到一个byte数组里解包就行。读完以后把coll(1)连续删LenCurMsg+8次(剩下的部分又是一条新消息的头部) 3.2 读出新消息的长度保存到LenCurMsg
jiaxueq 2017-09-09
  • 打赏
  • 举报
回复

引用 21 楼 Runnerchin 的回复:
建一个全局的Collection,比如叫coll。全局int变量LenCurMsg=0…………


捣鼓半天,死掉几亿脑细胞,憋出这几行代码,也不知对没对,小房间跑了个把小时没问题。
但是去个百万人气的大房间试了下,1,2分钟就出现 下标错误。


有时这里

有时这里


跑着跑着,字节数就不对了。


Dim Collection() As Byte, LenCurMsg As Integer
.................


Dim msgBytes() As Byte, msg As dataStrc
ReDim msgBytes(bytesTotal - 1)
Winsock1.GetData msgBytes

'--- 串接包
ReDim Preserve Collection(LenCurMsg + bytesTotal - 1)
CopyMemory Collection(LenCurMsg), msgBytes(0), bytesTotal
LenCurMsg = LenCurMsg + bytesTotal

Do While (LenCurMsg > 0)
'--- 从串接包读取包头指定的大小,解码
Dim packSize As Long
packSize = Collection(3) * 256 ^ 3 + Collection(2) * 256 ^ 2 + Collection(1) * 256 + Collection(0)
If LenCurMsg < packSize Then
WriteLog ("!小于包头指定大小,跳出")
Exit Sub
End If

ReDim tmpMsgBytes(packSize + 4 - 1) As Byte
CopyMemory tmpMsgBytes(0), Collection(0), packSize + 4
msg = UnpackMsg(tmpMsgBytes)
WriteLog ("从串接包(" & UBound(Collection) + 1 & ")取数据(" & packSize + 4 & "),内容:" & msg.content)

'--- 从串接包中移除已读数据
LenCurMsg = LenCurMsg - (packSize + 4)
If LenCurMsg = 0 Then
ReDim Collection(0)
WriteLog ("串接包=0")
Else
CopyMemory Collection(0), Collection(packSize + 4), LenCurMsg
ReDim Preserve Collection(LenCurMsg - 1)
End If
Loop



把焦点移到最后,方便观察

Private Sub WriteLog(msg As String)
'把焦点移到最后,方便观察
T1.Text = T1.Text & Format(Now, "yyyy-MM-dd HH:mm:ss") & vbTab & msg & vbCrLf & vbCrLf
T1.SelStart = Len(T1) - 1
If Len(T1) > 20000 Then T1.Text = ""
End Sub
jiaxueq 2017-09-08
  • 打赏
  • 举报
回复
引用 19 楼 Runnerchin 的回复:
点个赞,这样的话,这个代码就变成你自己的了。碰到问题拿出来大家讨论,这才是论坛真正的用法,而不是直接伸手拿个代码,什么自己的东西都没有。
嗯,谢谢Runnerchin。 不过这个粘包问题,查阅了好些帖子和博客,弄了一整个晚上了,确实没法搞定啊。(第一次接触) 希望能提供一下帮助。。。谢谢了。
X-i-n 2017-09-08
  • 打赏
  • 举报
回复
点个赞,这样的话,这个代码就变成你自己的了。碰到问题拿出来大家讨论,这才是论坛真正的用法,而不是直接伸手拿个代码,什么自己的东西都没有。
jiaxueq 2017-09-08
  • 打赏
  • 举报
回复
捣鼓半天,有点眉目,好像是前面 数据包尾加0,算到content里,导致包算错了。
移到后面就好了。
ReDim Preserve content(UBound(content) + 1)
content(UBound(content)) = 0

ReDim Preserve packbytes(12 + UBound(content))
CopyMemory packbytes(12), content(0), UBound(content) + 1



再看一下粘包的问题,不会再请教哈,谢谢。
jiaxueq 2017-09-08
  • 打赏
  • 举报
回复
抓包和正常对比了一下,好像是包的大小计算错了? 弄了半天也没改好,帮个忙吧。谢谢了。
jiaxueq 2017-09-08
  • 打赏
  • 举报
回复
引用 15 楼 Runnerchin 的回复:
API文档没有问题,我用别的环境重新实现了一遍,能正常抓到消息。 回过头我又重新看了一遍代码,SendBytes函数里面有个BUG,修复了以后可以正常抓到内容。具体问题在什么地方,你再琢磨一下,修正了BUG的代码我就不放上来了。
你说的sendBytes BUG和重写消息处理机制,还不怎么懂啊。 Runnerchin 大神,把改好的重新上传一下呀。谢谢了。
jiaxueq 2017-09-07
  • 打赏
  • 举报
回复
引用 2 楼 Runnerchin 的回复:
看了一下API,vb6写起来太费事,全程socket通信,但.net写出来估计你还是看得一头雾水
你的具体需求是什么?


这是上面那个有源码的C++实现的效果图。


就是想用VB来实现获取斗鱼某房间ID的弹幕,写入textbox1
看了C++的代码,也不是很长。主要是看不懂,而且还不知道用VB的winsock也能实现不。

jiaxueq 2017-09-07
  • 打赏
  • 举报
回复
Private Sub Command1_Click()
If Winsock1.State = sckClosed Then
Winsock1.RemoteHost = "openbarrage.douyutv.com"
Winsock1.RemotePort = 8601
Winsock1.Connect
End If
End Sub

Private Sub Command2_Click()
Dim data As String
data = "type@=loginreq/roomid@=301712/"
Winsock1.SendData data
'这样发过去,服务器好像不鸟你。。。,不返回数据回来。
'还要按照他的开发文档上写的,包含协议头。
'不会构建呀,VB实现感觉好麻烦了呢。
End Sub




这是C++定义的协议头
struct MsgInfo {
int len; //数据包长度
int code; //数据包长度
short magic; //消息类型
char temp1 = 0;//加密字段
char temp2 = 0;//保留字段
char c[1024]; //消息内容
}msg;


------- API文档关于协议头说明




data = "type@=loginreq/roomid@=301712/"
Winsock1.SendData data

我那直接发登陆消息过去,服务器不鸟我。
不知道VB怎么构建协议头呢?

X-i-n 2017-09-07
  • 打赏
  • 举报
回复
API文档没有问题,我用别的环境重新实现了一遍,能正常抓到消息。
回过头我又重新看了一遍代码,SendBytes函数里面有个BUG,修复了以后可以正常抓到内容。具体问题在什么地方,你再琢磨一下,修正了BUG的代码我就不放上来了。
除了这个BUG,这份代码还有一个问题,写DEMO的时候为了快速看到效果,所以没有处理粘包的情况,如果要正常用,需要重写一下消息处理机制,否则大流量的房间,再加上-9999分组,收不到几条消息就会解析错误,这种错一旦开始,一点纠正的余地都没有。具体做法是:用一个数组缓存将接收到的内容缓存起来,按消息头部的长度来确定消息边界,到了边界以后才去解析这个包,然后清空这条消息继续循环。

2017-09-07 22:46:31	--> LOGIN REQUEST
2017-09-07 22:46:31 * MSG SENT COMPLETE
2017-09-07 22:46:31 <-- MSG RECEIVED
长度:238Bytes
消息内容: type@=loginres/userid@=0/roomgroup@=0/pg@=0/sessionid@=0/username@=/nickname@=/live_stat@=0/is_illegal@=0/ill_ct@=/ill_ts@=0/now@=0/ps@=0/es@=0/it@=0/its@=0/npv@=0/best_dlev@=0/cur_lev@=0/nrc@=1651333632/ih@=0/sid@=70223/sahf@=0/
2017-09-07 22:46:32 --> JOIN
2017-09-07 22:46:32 * MSG SENT COMPLETE
2017-09-07 22:46:41 <-- MSG RECEIVED
长度:206Bytes
消息内容: type@=spbc/sn@=VVu的小跟班/dn@=VictorRiaVVu/gn@=火箭/gc@=1/drid@=2688739/gs@=5/gb@=0/es@=1/gfid@=196/eid@=143/bgl@=3/ifs@=0/rid@=244548/gid@=0/bid@=30125_1504795602_1153/sid@=11139172/cl2@=0/
2017-09-07 22:46:43 <-- MSG RECEIVED
长度:293Bytes
消息内容: type@=chatmsg/rid@=244548/ct@=1/uid@=42494976/nn@=无趣逗哥/txt@=进城了/cid@=9f0f98ac32c4463f0061010000000000/ic@=avanew@Sface@S201704@S18@S12@S739b682ec1e837792ef658ccd1d3b5af/level@=17/sahf@=0/bnn@=/bl@=0/brid@=0/hc@=/el@=eid@AA=1500000113@ASetp@AA=1@ASsc@AA=1@ASef@AA=0@AS@S/
2017-09-07 22:46:50 <-- MSG RECEIVED
长度:255Bytes
消息内容: type@=chatmsg/rid@=244548/ct@=1/uid@=85641846/nn@=765235626/txt@=倒奶现在播的什么?/cid@=9f0f98ac32c4463f5c61010000000000/ic@=avanew@Sface@S201704@S17@S07@S85e270c8a6961714ecb4b8231146e44c/level@=22/sahf@=0/bnn@=/bl@=0/brid@=0/hc@=/el@=/
2017-09-07 22:46:51 <-- MSG RECEIVED
长度:343Bytes
消息内容: type@=chatmsg/rid@=244548/ct@=1/uid@=40457391/nn@=霸气的加菲猫/txt@=流弊/cid@=9f0f98ac32c4463f6561010000000000/ic@=avanew@Sface@S201705@S13@S01@Sef10f63e4acdf2bdda0eaaf535d5c974/level@=27/sahf@=0/bnn@=叶灬子/bl@=11/brid@=244548/hc@=01c71d57378b57aa3394a48356270b6b/el@=eid@AA=1500000113@ASetp@AA=1@ASsc@AA=1@ASef@AA=0@AS@S/
2017-09-07 22:46:53 <-- MSG RECEIVED
长度:340Bytes
消息内容: type@=chatmsg/rid@=244548/uid@=25258628/nn@=我爱单色凌4/txt@=到哪里了/cid@=9f0f98ac32c4463f7761010000000000/ic@=avanew@Sface@S201708@S02@S21@S1ad33029efde508c66b64c30b473d13b/level@=16/sahf@=0/bnn@=叶灬子/bl@=7/brid@=244548/hc@=01c71d57378b57aa3394a48356270b6b/el@=eid@AA=1500000113@ASetp@AA=1@ASsc@AA=1@ASef@AA=0@AS@S/
2017-09-07 22:46:53 <-- MSG RECEIVED
长度:64Bytes
消息内容: rid@=244548/sc@=5800/sctn@=0/rid@=-1/type@=qausrespond/
2017-09-07 22:46:54 <-- MSG RECEIVED
长度:261Bytes
消息内容: type@=chatmsg/rid@=244548/ct@=1/uid@=38202744/nn@=九龙湖广州户外娱乐/txt@=鬼子进城了/cid@=9f0f98ac32c4463f9a61010000000000/ic@=avanew@Sface@S201702@S21@S01@Sf29c2c7ef9363397b2835180f265d18b/level@=15/sahf@=0/bnn@=/bl@=0/brid@=0/hc@=/el@=/
2017-09-07 22:46:55 <-- MSG RECEIVED
长度:209Bytes
消息内容: type@=spbc/sn@=等一个天气晴/dn@=ASMR猫心儿/gn@=火箭/gc@=1/drid@=2098162/gs@=5/gb@=0/es@=1/gfid@=196/eid@=143/bgl@=3/ifs@=0/rid@=244548/gid@=0/bid@=30027_1504795616_1566/sid@=1576557/cl2@=0/
2017-09-07 22:46:58 <-- MSG RECEIVED
长度:374Bytes
消息内容: type@=chatmsg/rid@=244548/ct@=1/uid@=29049637/nn@=果果淘之妖妖/txt@=阿科 骑慢点 看你直播两年了/cid@=9f0f98ac32c4463fc561010000000000/ic@=avanew@Sface@S201706@S02@S10@S79d2db43a941dd6d25ce6d70734e486a/level@=21/sahf@=0/bnn@=神刀門/bl@=6/brid@=287471/hc@=4c586e56a669d6d26e279b5d3b9968e0/el@=eid@AA=1500000113@ASetp@AA=1@ASsc@AA=1@ASef@AA=0@AS@S/
2017-09-07 22:47:01 --> KEEPALIVE PACKAGE
2017-09-07 22:47:01 * MSG SENT COMPLETE
2017-09-07 22:47:01 <-- MSG RECEIVED
长度:20Bytes
消息内容: type@=mrkl/
2017-09-07 22:47:11 <-- MSG RECEIVED
长度:64Bytes
消息内容: rid@=244548/sc@=5800/sctn@=0/rid@=-1/type@=qausrespond/
舉杯邀明月 2017-09-07
  • 打赏
  • 举报
回复
引用 5 楼 jiaxueq 的回复:
'按照文档说明,弄好了协议头的格式。。。 Public Type dataStrc len1 As Long len2 As Long smsType As Integer tmpstr1 As String tmpstr2 As String content As String End Type ‘---------------------------------- Private Sub Command2_Click() Dim sendData As dataStrc sendData.smsType = 689 sendData.content = "type@=loginreq/roomid@=301712/" sendData.tmpstr1 = 0 sendData.tmpstr2 = 0 sendData.len1 = LenB(sendData.smsType) + LenB(sendData.content) + LenB(sendData.tmpstr1) + LenB(sendData.tmpstr2) sendData.len2 = sendData.len1 Winsock1.sendData sendData '---------蛋疼,winsock不支持这样发送。。。。 End Sub
你的这个“类型定义”根本就不正确! 按你在3楼说的 C++的结构体定义: 这是C++定义的协议头 struct MsgInfo { int len; //数据包长度 int code; //数据包长度 short magic; //消息类型 char temp1 = 0;//加密字段 char temp2 = 0;//保留字段 char c[1024]; //消息内容 }msg; 应该是这样:
Public Type dataStrc
    len1 As Long
    len2 As Long
    smsType As Integer
    tmpstr1 As Byte
    tmpstr2 As Byte
    content(1023) As Byte
End Type
X-i-n 2017-09-07
  • 打赏
  • 举报
回复
写一个Function,计算完数据长度以后,把dataStrc对象拼成string
X-i-n 2017-09-07
  • 打赏
  • 举报
回复
我试了一下,加入组的时候,完全没有回包。有空我用别的办法测一下看看
jiaxueq 2017-09-07
  • 打赏
  • 举报
回复
引用 10 楼 Runnerchin 的回复:
还有个示意图忘贴了


纳尼,试了一下,有3个问题不明白。

1. 为什么要按2次连接,发送2次(*MSG SENT),服务器才回应信息呢? 不是发送过去,只要数据正确就应该回应么?

2.试了几个正在直播的房间ID,回应的数据live_stat@=0,都是0,未开播状态。奇怪了。

3.尝试加入分组,获取弹幕,服务器为啥没回应消息呢,格式是按API文档写的呀。

Private Sub Command1_Click()
WriteLog ("LOGIN REQUEST")
Dim loginpac As dataStrc
With loginpac
.content = "type@=loginreq/roomid@=218859/"
.smsType = 689
End With
Winsock1.SendData SendBytes(loginpac)
End Sub

Private Sub Command2_Click()
WriteLog ("JOIN_GROUP")
Dim loginpac As dataStrc
With loginpac
.content = "type@=joingroup/rid@=218859/gid@=-9999/"
.smsType = 689
End With
Winsock1.SendData SendBytes(loginpac)
End Sub

加载更多回复(8)

1,502

社区成员

发帖
与我相关
我的任务
社区描述
VB 网络编程
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧