winsock循环发送与接收数据的问题

时间:2022-12-15 15:28:33
用Winsock在两机间发送一个很大的位图,用byte数组保存,因无法一次全部发送,要分多次,于是循环进行senddata,但在接收端发生DataArrival事件时,似乎不是每个senddata都触发一次该事件,其参数bytesTotal是每次累加的吗?何时才会清空?接收端应如何响应才能保证数据正确接收?
还有:我发送的2048个字节,接收时却变成了2049个,不知何故?
另:哪有详细介绍VB中winsock原理的资料?或者大文件传输(含接收与发送)的代码?

22 个解决方案

#1


劳烦各位大侠请指点一二,急煞我也

#2


我也在急这个问题

#3


2049是因为加了数据流结束符

#4


crycoming:是否第2049字符在接收时要去掉?

#5


需要例程吗?留mail

注:解决办法是加上停止等待协议

#6


我是这么做的:
Private Sub tcpServer_DataArrival (ByVal bytesTotal As Long)

    Dim ArrivedArray() As Byte
    ReDim ArrivedArray(bytesTotal) As Byte
    Dim i As Integer
    
    Dim strFilePath2 As String
    strFilePath2 = "D:\3.jpg"
    
    tcpServer.GetData ArrivedArray, vbArray + vbByte, bytesTotal
    Data(UBound(Data)) = ArrivedArray
    If bytesTotal < 8192 Then   '8192是每次发送的最大的数据块大小
        Open strFilePath2 For Binary Access Write As #1
            For i = LBound(Data) To UBound(Data)
                ArrivedArray = Data(i)
                MsgBox (UBound(ArrivedArray))
                Put #1, , ArrivedArray
            Next
        Close #1
        Exit Sub
    End If
    
    
    ReDim Preserve Data(UBound(Data) + 1)
        
    
End Sub

#7


对一个字节可能是因为你用的redim by(2048)因为数组是从0开始的。所以你redim by(2048)定义的数组的打小是2049

至于发送文件。我可以个你一个我写的发送文件的类。很好用。最重要的是你可以看它的代码自己写一个。

#8


 hydnoahark(诺亚方舟):谢谢,又是您救人于水火。从您的程序来看,字节数参数不是累加的,而是每接收到一次数组的字节数,对吗?可今天上午我单步调试程序的时候发现每次接收的数据字节数都不一样,而且是越来越大,而我每次循环发的都是2K字节,这是怎么回事呢?
gameboy999和pp616朋友:谢谢你们,我的邮箱是:managerhua@huamai.com.cn

#9


朋友们:你们在线上吗?

#10


高手回复一下

#11


我建议你在发送二进制数据之前用自定义的控制信号(字符串),来保证传输的准确性,至于传送的字节数你可以不必管它,在客户端上建立一个相同的文件,只要依次向里面写二进制数据即可.
处理时注意文件的结尾处及空文件

#12


我将块的大小定为8K,发送了10块,最后一块未满;
接收的时候,总字节数多出10个字节,但每块还是8K,可以每块多了一个结束标志,但不知要如何处理。

#13


可以先用函数getbitmapbits得到位图数组PicBit()。直接使用winsock1.senddata PicBit
发送数据.只是数据接受端麻烦了点。

#14


http://www.wangfeng.org/vbclub/login.asp 

#15


http://www.wangfeng.org/vbclub/login.asp 

#16


http://www.wangfeng.org/vbclub/login.asp 

#17


在数据接收端我发现一个有趣的现象。使用GetData PicBit(1) bytesTotal是垒加。记第一次是8092 ,第二次是16184.......如果是GetData Buff ,bytesTotal是8092(文件大于8092).而且如果用函数检测数组UBound(Buff)=8091 .而不是8092。当选用第一种方法时
winsock控件负责填充整个数组但是最后会发现,数组比原始数组要小。所以只能使用第二种方法。要自己实现数组的拼接。

#18


上面的PicBit , Buff皆为字节数组。

#19


用CRC校验数据的正确性

#20


wangfeng(进阶C#) :老兄你搞什么,我在你的站上登录了一个同样的名字,然后怎么办呢?
这个小程序困扰我一个星期了,头都搞大了,别再开玩笑了。

jlum99:你说的两种方法有什么不一样,我好象还没看出来。 我正是用函数getbitmapbits得到位图数组PicBit()。直接使用winsock1.senddata PicBit发送数据.数据接受端怎么办,再指点指点。谢了。 

#21


在数据接收端我发现一个有趣的现象。使用GetData PicBit(1) bytesTotal是垒加。记第一次是8092 ,第二次是16184.......如果是GetData Buff ,bytesTotal是8092(文件大于8092).而且如果用函数检测数组UBound(Buff)=8091 .而不是8092。当选用第一种方法时
winsock控件负责填充整个数组但是最后会发现,数组比原始数组要小。所以只能使用第二种方法。要自己实现数组的拼接。

就是上面的不同啊!就是说当给GetData函数传入不同形式的参数.得道的结果不同.一个市数组的第一个元素.在调用api函数时,相当于数组的指针.一个是数组名称.在c里可以作为数组的指针.在vb里我也有些犯迷糊.但结果肯定不同.这是我写的数据接收段的代码.效率不高.
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Dim PicBits() As Byte
Dim buff() As Byte
Dim lAlreadyTran As Long
Private Sub Command1_Click()
ReDim PicBits(0) As Byte
lAlreadyTran = 0
ws2.Close
ws2.Listen
End Sub

Private Sub Form_Load()
ws2.Bind 10001, "127.0.0.1"
ws2.Listen
lAlreadyTran = 0
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
ws2.Close
Picture1 = Nothing
End Sub
Private Sub ws2_ConnectionRequest(ByVal requestID As Long)
ws2.Close
ws2.Accept requestID
End Sub

Private Sub ws2_DataArrival(ByVal bytesTotal As Long)
Dim i As Long
Dim j As Long
Dim dummy() As Byte
ReDim buff(bytesTotal) As Byte
ws2.GetData buff, vbbytes, bytesTotal
ReDim dummy(lAlreadyTran) As Byte
For j = 1 To lAlreadyTran
    dummy(j) = PicBits(j)
Next
ReDim PicBits(lAlreadyTran + bytesTotal)
For j = 1 To lAlreadyTran
    PicBits(j) = dummy(j)
Next
ReDim dummy(0) As Byte
For i = 1 To bytesTotal
   PicBits(lAlreadyTran + i) = buff(i - 1)
Next

lAlreadyTran = lAlreadyTran + bytesTotal

SetBitmapBits Picture1.Image, lAlreadyTran, PicBits(1)
Picture1.Refresh
End Sub
多给点分吧! :)

#22


jlum99(闲人):你的代码我还没来得及仔细推敲,等会儿我把它拷贝下来打印一份。
由于这段代码编得时间太长了,无奈何,我只好还是用了传文件的方法,先抓图存为文件,再用WINSOCK传输到控制端。传文件的方法很顺利,现已经可监视屏幕了,当然我认为传数据流是最好的方法,等我按你的方法试试再向你请教。
我觉得不可思议的是:其实传文件与传数据是一个道理,只是一个是接收到一块后写到文件中,为什么它就不出错呢?
另你说的数据累加的情况我在用PEEKDATA时有这种情况,但用GETDATA时就没有了,我想后者自动清了缓冲区吧。
真的很感谢你。加了一点分,不好意思太少了。
 

#1


劳烦各位大侠请指点一二,急煞我也

#2


我也在急这个问题

#3


2049是因为加了数据流结束符

#4


crycoming:是否第2049字符在接收时要去掉?

#5


需要例程吗?留mail

注:解决办法是加上停止等待协议

#6


我是这么做的:
Private Sub tcpServer_DataArrival (ByVal bytesTotal As Long)

    Dim ArrivedArray() As Byte
    ReDim ArrivedArray(bytesTotal) As Byte
    Dim i As Integer
    
    Dim strFilePath2 As String
    strFilePath2 = "D:\3.jpg"
    
    tcpServer.GetData ArrivedArray, vbArray + vbByte, bytesTotal
    Data(UBound(Data)) = ArrivedArray
    If bytesTotal < 8192 Then   '8192是每次发送的最大的数据块大小
        Open strFilePath2 For Binary Access Write As #1
            For i = LBound(Data) To UBound(Data)
                ArrivedArray = Data(i)
                MsgBox (UBound(ArrivedArray))
                Put #1, , ArrivedArray
            Next
        Close #1
        Exit Sub
    End If
    
    
    ReDim Preserve Data(UBound(Data) + 1)
        
    
End Sub

#7


对一个字节可能是因为你用的redim by(2048)因为数组是从0开始的。所以你redim by(2048)定义的数组的打小是2049

至于发送文件。我可以个你一个我写的发送文件的类。很好用。最重要的是你可以看它的代码自己写一个。

#8


 hydnoahark(诺亚方舟):谢谢,又是您救人于水火。从您的程序来看,字节数参数不是累加的,而是每接收到一次数组的字节数,对吗?可今天上午我单步调试程序的时候发现每次接收的数据字节数都不一样,而且是越来越大,而我每次循环发的都是2K字节,这是怎么回事呢?
gameboy999和pp616朋友:谢谢你们,我的邮箱是:managerhua@huamai.com.cn

#9


朋友们:你们在线上吗?

#10


高手回复一下

#11


我建议你在发送二进制数据之前用自定义的控制信号(字符串),来保证传输的准确性,至于传送的字节数你可以不必管它,在客户端上建立一个相同的文件,只要依次向里面写二进制数据即可.
处理时注意文件的结尾处及空文件

#12


我将块的大小定为8K,发送了10块,最后一块未满;
接收的时候,总字节数多出10个字节,但每块还是8K,可以每块多了一个结束标志,但不知要如何处理。

#13


可以先用函数getbitmapbits得到位图数组PicBit()。直接使用winsock1.senddata PicBit
发送数据.只是数据接受端麻烦了点。

#14


http://www.wangfeng.org/vbclub/login.asp 

#15


http://www.wangfeng.org/vbclub/login.asp 

#16


http://www.wangfeng.org/vbclub/login.asp 

#17


在数据接收端我发现一个有趣的现象。使用GetData PicBit(1) bytesTotal是垒加。记第一次是8092 ,第二次是16184.......如果是GetData Buff ,bytesTotal是8092(文件大于8092).而且如果用函数检测数组UBound(Buff)=8091 .而不是8092。当选用第一种方法时
winsock控件负责填充整个数组但是最后会发现,数组比原始数组要小。所以只能使用第二种方法。要自己实现数组的拼接。

#18


上面的PicBit , Buff皆为字节数组。

#19


用CRC校验数据的正确性

#20


wangfeng(进阶C#) :老兄你搞什么,我在你的站上登录了一个同样的名字,然后怎么办呢?
这个小程序困扰我一个星期了,头都搞大了,别再开玩笑了。

jlum99:你说的两种方法有什么不一样,我好象还没看出来。 我正是用函数getbitmapbits得到位图数组PicBit()。直接使用winsock1.senddata PicBit发送数据.数据接受端怎么办,再指点指点。谢了。 

#21


在数据接收端我发现一个有趣的现象。使用GetData PicBit(1) bytesTotal是垒加。记第一次是8092 ,第二次是16184.......如果是GetData Buff ,bytesTotal是8092(文件大于8092).而且如果用函数检测数组UBound(Buff)=8091 .而不是8092。当选用第一种方法时
winsock控件负责填充整个数组但是最后会发现,数组比原始数组要小。所以只能使用第二种方法。要自己实现数组的拼接。

就是上面的不同啊!就是说当给GetData函数传入不同形式的参数.得道的结果不同.一个市数组的第一个元素.在调用api函数时,相当于数组的指针.一个是数组名称.在c里可以作为数组的指针.在vb里我也有些犯迷糊.但结果肯定不同.这是我写的数据接收段的代码.效率不高.
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Dim PicBits() As Byte
Dim buff() As Byte
Dim lAlreadyTran As Long
Private Sub Command1_Click()
ReDim PicBits(0) As Byte
lAlreadyTran = 0
ws2.Close
ws2.Listen
End Sub

Private Sub Form_Load()
ws2.Bind 10001, "127.0.0.1"
ws2.Listen
lAlreadyTran = 0
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
ws2.Close
Picture1 = Nothing
End Sub
Private Sub ws2_ConnectionRequest(ByVal requestID As Long)
ws2.Close
ws2.Accept requestID
End Sub

Private Sub ws2_DataArrival(ByVal bytesTotal As Long)
Dim i As Long
Dim j As Long
Dim dummy() As Byte
ReDim buff(bytesTotal) As Byte
ws2.GetData buff, vbbytes, bytesTotal
ReDim dummy(lAlreadyTran) As Byte
For j = 1 To lAlreadyTran
    dummy(j) = PicBits(j)
Next
ReDim PicBits(lAlreadyTran + bytesTotal)
For j = 1 To lAlreadyTran
    PicBits(j) = dummy(j)
Next
ReDim dummy(0) As Byte
For i = 1 To bytesTotal
   PicBits(lAlreadyTran + i) = buff(i - 1)
Next

lAlreadyTran = lAlreadyTran + bytesTotal

SetBitmapBits Picture1.Image, lAlreadyTran, PicBits(1)
Picture1.Refresh
End Sub
多给点分吧! :)

#22


jlum99(闲人):你的代码我还没来得及仔细推敲,等会儿我把它拷贝下来打印一份。
由于这段代码编得时间太长了,无奈何,我只好还是用了传文件的方法,先抓图存为文件,再用WINSOCK传输到控制端。传文件的方法很顺利,现已经可监视屏幕了,当然我认为传数据流是最好的方法,等我按你的方法试试再向你请教。
我觉得不可思议的是:其实传文件与传数据是一个道理,只是一个是接收到一块后写到文件中,为什么它就不出错呢?
另你说的数据累加的情况我在用PEEKDATA时有这种情况,但用GETDATA时就没有了,我想后者自动清了缓冲区吧。
真的很感谢你。加了一点分,不好意思太少了。