| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 6751 人关注过本帖
标题:VB winsock接收数据处理的问题
取消只看楼主 加入收藏
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
结帖率:0
收藏
已结贴  问题点数:20 回复次数:19 
VB winsock接收数据处理的问题
在接收数据时,数据长度不定,但是有一组数据比较大,是分多个包发送过来的,其中第一个包中有整个数据的长度,当遇到这个数据是,怎么样处理才能把所有的数据接收完,并放入一个数组或是字串中?
本人小白,请高手指点
搜索更多相关主题的帖子: 空间设计 
2015-04-23 00:51
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
我的源码如下,请大神帮忙看看中间红色部分该如何处理取完整数据
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim S, S3, s1, flag, flag1 As String
Dim id, strlen As Integer
Dim tmp As String
Dim str() As Byte
Winsock1.getData str()
strdata = StrConv(str(), vbUnicode)                                    '转换为字符串,
flag = Left(strdata, 2)

'log.Text = log.Text & Format(Hour(Time), "00") & ":" & Format(Minute(Time), "00") & ":" & Format(Second(Time), "00") & " " & strdata   '显示日志
'log.SelStart = Len(log.Text)

Select Case flag
   
   Case "E1"                                        '登录
      Sleep 200
      Login   '登录
      log.Text = log.Text & Format(Hour(Time), "00") & ":" & Format(Minute(Time), "00") & ":" & Format(Second(Time), "00") & " " & "admin" & vbCrLf  '显示日志

  Case "E0"
       u = u + 1
       log.Text = log.Text & Format(Hour(Time), "00") & ":" & Format(Minute(Time), "00") & ":" & Format(Second(Time), "00") & " " & strdata   '显示日志
       log.SelStart = Len(log.Text)
        If u = 1 Then
    '     Sleep 500
        log.Text = log.Text & Format(Hour(Time), "00") & ":" & Format(Minute(Time), "00") & ":" & Format(Second(Time), "00") & " " & "登录成功" & vbCrLf   '显示日志
        state_lab = "TCP/IP Connect OK"                  '登录成功
        log.SelStart = Len(log.Text)
        End If
  Case "EA"                                         '温度值返回
       S = strdata
       log.Text = log.Text                          '不显示日志
       log.SelStart = Len(log.Text)
        S3 = Split(S, "^C", , vbTextCompare)
        For j = 1 To UBound(S3)
            s1 = Split(S3(j), vbCrLf)(0)
            s1 = Trim(s1)
            If Format(s1) > Val(Form4.CH(j - 1)) Then
            Form4.CH(j - 1) = Format(s1, "00.0")
            End If
        Next j
        
  Case "EB"                                         '二进制数据返回,
      tmp = StrConv(str(), vbUnicode)
      id = str(9)                                   '取ID ,测试ok
      strlen = HEX_to_DEC(Hex(str(4)) & Hex(str(5)) & Hex(str(6)) & Hex(str(7)))            '取数据长度,测试OK
     
   在此位置该如何处理才能先接收全部的数据??
  数据格式和使用Wireshark抓包的数据截图如下图


      If id = 19 Then                               '如果ID为19,则为设定信息输出   
       此处为对接收的数据进行处理,同上面温度值取出
      End If
End Select

图片附件: 游客没有浏览图片的权限,请 登录注册
图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 hcyang1422 于 2015-4-23 12:48 编辑 ]
2015-04-23 12:39
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 5楼 lianyicq
其它包没有FLAG标志,
能帮忙写一下代码吗?
2015-04-23 13:58
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 7楼 lianyicq
不可以使用case else的吧,因为接收到的数据文件类型还可能是不一样的,是要根据头包中的ID位来区分后再处理的。是否能在头包的case中,根据数据长度来完成接收呢?
2015-04-23 17:30
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 9楼 renxiaoyao36
第一次GETDATA,得到的只是头包,后面还有多个包呢,该怎么处理才能把后面的数据也GETDATA,并和前面的包合在一起?
2015-04-23 20:13
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 11楼 lianyicq
我再说明一下情况,我是通过winsock向仪器发出一条查询指令,然后仪器就开始通过异步方式返回数据,即仪器通过本身的协仪设定,开始不停的发送数据,直到数据发送完成。
返回的数据根据查询指令的不同,数据长度也不同,大部分数据一次GETDATA可以接收完成,但是当出现"EB"开头的数据时,返回数据的格式如之前提供的图片(12byte包头+DATA包+……+DATA包+校验和包),
不能一次GETDATA就接收完成,所以就只能考虑通过包头中的数据长度来进行特别处理,以完成接收全部数据,这也正是我搞不定,来求助的内容。
2015-04-23 22:36
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 13楼 renxiaoyao36
我就是GETDATA后,先检查是否是头包标志,当出现较长的数据时,先取出数据长度的,后面的接收合并过程不太会处理。
请问,用下面红色代码进行接收后面的数据并合并,可以吗?不行的话请帮忙修改一下。
Case "EB"                                         '二进制数据返回,
      tmp = StrConv(str(), vbUnicode)
      id = str(9)                                   '取ID ,测试ok
      strlen = HEX_to_DEC(Hex(str(4)) & Hex(str(5)) & Hex(str(6)) & Hex(str(7)))            '取数据长度,测试OK
    if len(tmp)<strlen +8 then                '如果当前数据长度小于取得的当前数据量长度
     winsock1.getdata str()                    '再次取出数据
     tmp=tmp & strconv(str(),vbunicode)        '数据合并
     end if

         If id = 19 Then                               '如果ID为19,则为设定信息输出   
       此处为对接收的数据进行处理,同上面温度值取出
      End If
End Select
2015-04-24 08:36
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 17楼 lianyicq
非常感谢您能抽空写代码帮我解决问题,可惜本人太小白了,依然没有领悟出解决方法。
现在针对我的问题,我有以下方案,
我只有对仪器发出两组命令的时候才会出现数据量大于8192字节的情况
所以我在发出命令后设置一个状态符dataflag=true
接收端处理时,当状态符为dataflag=true时以byte型接收,否则以string型接收
但是在出现byte型数据时,我的代码仍然不能按预期接收数据,
经实测,数据长度每次会递增12字节,但是全部为0.请帮忙看看此处如何修改才能完整的接收数据。
为便于分析问题,再次添加数据格式以及仪器输出数据时使用Wireshark抓取的数据包
接收代码如下
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim S, S3, s1, flag, flag1 As String
Dim id, strlen As Integer
Dim tmp As String
Dim str(), tmp() As Byte
Dim lngDataSize As Long

lngDataSize = 0                                                                            '初始化接收到的数据量
ReDim str(bytesTotal - 1)                                                                  '初始化接收缓冲区
'=======================================
'数据接收过程
'=======================================
If dataflag Then                                                                        '判断接收类型,为真时,接收类型为Byte
    '循环接收数据,直到接收数据长度等于应收数据长度
    Do
    Winsock1.getData str, vbByte + vbArray
    id = str(9)                                                                            '取ID ,测试ok
    strlen = HEX_to_DEC(Hex(str(4)) & Hex(str(5)) & Hex(str(6)) & Hex(str(7)))             '取数据长度,完整数据长度为此长度+8
    ReDim tmp(lngDataSize + bytesTotal - 1) As Byte
    copymemory tmp(), str(0), bytesTotal
    lngDataSize = lngDataSize + bytesTotal
    loop until  lngDataSize=stren+8               
                                       
   
    '数据接收完成后的预处理
    strdata = StrConv(str(), vbUnicode)                                                    '转换为字符串,
    flag = Left(strdata, 2)                                                                '取数据类型标志
   
    Else
    Winsock1.getData strdata                                                               '接收类型为string
    flag = Left(strdata, 2)
End If
'===================================
'     接收数据处理过程
'===================================
Select Case flag                                   '数据处理类型标志   
  Case "E1"                                        '登录     
  Case "E0"      
  Case "EA"                                         '温度值返回
  Case "EB"                                         '二进制数据返回,
data format&Wireshark data.rar (29.03 KB)


[ 本帖最后由 hcyang1422 于 2015-4-30 16:27 编辑 ]
2015-04-30 16:25
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 19楼 lianyicq
非常感谢抽空帮我解决问题
按照你给的方法我进行了测试,在下面这句代码处出现下标越界错误
ReDim FileByte(UBound(temp) - 14)
我将代码作如下变更后
ReDim FileByte(UBound(temp) - 1)
          CopyMemory FileByte(0), temp(11), UBound(temp) - 1
未再出现错误提示,
但是If Loc(1) = strlen Then这句运行结果一直为false
我查看临时文件temp.bat,里面只有8k的数据,后面的数据未接收到。

另外Loc(1) = strlen这句代码中的1代表的就是上面产生的临时数组#1吗?
在后面的处理中,如果我要把全部的数据转换为字符串,
是否可以用tmp=StrConv(1, vbUnicode)得到全部20多K数据?

[ 本帖最后由 hcyang1422 于 2015-5-4 17:00 编辑 ]
2015-05-04 16:34
hcyang1422
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2015-4-23
收藏
得分:0 
回复 21楼 lianyicq
我将代码作如下变更后
temp=str()
ReDim FileByte(UBound(temp) - 1)
          CopyMemory FileByte(0), temp(11), UBound(temp) - 1
未再出现错误提示,
但是If Loc(1) = strlen Then这句运行结果一直为false
我查看临时文件temp.bat,里面只有8k的数据,后面的数据未接收到。

现在这部分的接收和处理代码如下
请再帮忙看下8K之后数据未收到的原因,以及后面信息处理时全部数据转换字符串的过程是否正确。

  Case "EB"                                         '二进制数据返回,
       If ReceiveState = False Then
             Open "c:\temp.dat" For Binary As #1
             ReceiveState = True
             id = str(9)
          End If
          strlen = HEX_to_DEC(Hex(str(4)) & Hex(str(5)) & Hex(str(6)) & Hex(str(7))) + 8 '取数据长度,测试OK
          temp = str()
          ReDim FileByte(UBound(temp) - 14)
          copymemory FileByte(0), temp(12), UBound(temp) - 13
          Put #1, , FileByte
          If Loc(1) = strlen Then
             ReceiveState = False
             Select Case id
               Case id = 19                                                            'id为19时,取通道标记
               tmp = Mid(StrConv(1, vbUnicode), 6000, 10000)                           '将全部数据转换为字符串
               S3 = Split(tmp, "ST", , vbBinaryCompare)   '字符串分解,区分大小写
                'Text4.Text = Trim(s3)
                For i = 1 To UBound(S3)
                    s1 = Split(Split(S3(i), vbCrLf)(0), ",")(1)
                    s1 = Trim(s1)
                    Text2 = Text2 + s1 + vbCrLf
                    Form4.CHNAME(j - 1) = Trim(s1)
                Next i
                Case id=13
              End Select

'命令发送完成后,添加有如下状态设置,未全部接收数据是否与此有关?
Private Sub Winsock1_SendComplete()
If sdata = "FE4" Or sdata = "FC GET" Then
ReceiveState = 1
Else
ReceiveState = 0

End If
End Sub

[ 本帖最后由 hcyang1422 于 2015-5-4 17:26 编辑 ]
2015-05-04 17:19
快速回复:VB winsock接收数据处理的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.040176 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved