这是发送端的代码:
Dim myfile() As Byte
Dim position As Long Open "C:\1.bmp" For Binary As #1 position = 0 Do While Not EOF(1)
position = position + 1
ReDim Preserve myfile(1 To position)
Get #1, , myfile(position)
Loop Close #1 sockserver.SendData myfile接受端代码:
Private Sub sockclient_DataArrival(ByVal bytestotal As Long)
Dim i As Long
Dim receiveFile() As Byte
ReDim receiveFile(1 To bytestotal)
sockclient.GetData receiveFile, vbArray + vbByte Open "c:\A.BMP" For Binary As #1
For i = 1 To bytestotal
Put #1, , receiveFile
Next i
Close #1
End Sub但是这样子接受到的文件的大小变小了,我发现发送方一次发送过来数据,但是接受方会发生好几次DataArrival事件,怎么样把所有的数据都接受到呢?谢谢。
Dim myfile() As Byte
Dim position As Long Open "C:\1.bmp" For Binary As #1 position = 0 Do While Not EOF(1)
position = position + 1
ReDim Preserve myfile(1 To position)
Get #1, , myfile(position)
Loop Close #1 sockserver.SendData myfile接受端代码:
Private Sub sockclient_DataArrival(ByVal bytestotal As Long)
Dim i As Long
Dim receiveFile() As Byte
ReDim receiveFile(1 To bytestotal)
sockclient.GetData receiveFile, vbArray + vbByte Open "c:\A.BMP" For Binary As #1
For i = 1 To bytestotal
Put #1, , receiveFile
Next i
Close #1
End Sub但是这样子接受到的文件的大小变小了,我发现发送方一次发送过来数据,但是接受方会发生好几次DataArrival事件,怎么样把所有的数据都接受到呢?谢谢。
重新写一个,不要用FOR循环来写,就算真要用FOR也别在DATAARRIVAL事件里用
然后从其他的地方读缓冲的数据
Dim myfile() As Byte
Dim position As Long position = FileLen("C:\1.bmp")
ReDim myfile(position - 1) As Byte
Open "C:\1.bmp" For Binary As #1
Get #1, 1, myfile
Close #1 sockserver.SendData myfile½ÓÊܶ˴úÂë:
Private Sub sockclient_DataArrival(ByVal bytestotal As Long)
Dim i As Long
Dim receiveFile() As Byte
sockclient.GetData receiveFile Open "c:\A.BMP" For Binary As #1
Put #1, , receiveFile
Close #1
End Sub注意:你发送的文件不能太大!
我还有个自己写的关于winsock的程序,后面补上
Dim myfile() As Byte
Dim position As Long position = FileLen("C:\1.bmp")
ReDim myfile(position - 1) As Byte
Open "C:\1.bmp" For Binary As #1
Get #1, 1, myfile
Close #1 sockserver.SendData myfile接受端代码:
Private Sub sockclient_DataArrival(ByVal bytestotal As Long)
Dim i As Long
Dim receiveFile() As Byte
sockclient.GetData receiveFile Open "c:\A.BMP" For Binary As #1
Put #1, , receiveFile
Close #1
End Sub
'RemoteFilePath 是个远端接收文件的地址(包含全路经,不包括文件名)
'WinS是个Winsock对象,objProBar是个进度条对象
'const SendDataSize =1024
Dim FreeF As Integer
Dim LenFile As Long
Dim nCnt As Long
Dim LocData() As Byte
Dim Tempstr As String
Dim a() As Byte
Dim i As Long
Dim myHead As StringFreeF = FreeFile
Open FileName For Binary As FreeF nCnt = 1
LenFile = FileLen(FileName)
Tempstr = IIf(Right$(RemoteFilePath, 1) = "\", RemoteFilePath & _
Right$(FileName, Len(FileName) - InStrRev(FileName, "\")), RemoteFilePath & _
"\" & Right$(FileName, Len(FileName) - InStrRev(FileName, "\")))
myHead = "|FILESEND|" & Tempstr & "|" & CStr(LenFile)
WinS.SendData myHead '发送头和文件名及文件总长度!
objProBar.Value = 0
objProBar.Max = Fix(LenFile / SendDataSize) + 1
objProBar.Visible = True
Sleep (300) '一个api函数
Do Until nCnt > (LenFile)
DoEvents
If nCnt + SendDataSize - 1 > LenFile Then
ReDim LocData(LenFile - nCnt) As Byte
Else
ReDim LocData(SendDataSize - 1) As Byte
End If
Get FreeF, nCnt, LocData 'Get data from the file nCnt is from where to start the get
WinS.SendData LocData
nCnt = nCnt + SendDataSize
objProBar.Value = objProBar.Value + 1
Loop
Close FreeF
objProBar.Value = objProBar.Max
objProBar.Visible = False
End Sub'我自己的接收端程序:Private Sub objTCP_DataArrival(Index As Integer, ByVal bytesTotal As Long) Dim strData As String
Dim sData As String
Dim lRet As Long
Dim DataByte() As Byte
objTCP(intmax).GetData DataByte
strData = StrConv(DataByte, vbUnicode)
If Is_FILESEND = True Then 'Is_FILESEND是个全局变量
Put #myFreeFile, , DataByte
SendFileLen = SendFileLen - UBound(DataByte) - 1
If SendFileLen <= 0 Then
Close #myFreeFile
myFreeFile = 0
Is_FILESEND = False
End If
Else
If InStr(1, strData, "|FILESEND|") <> 0 Then
Dim sFileName As String
Dim k As Integer
Is_FILESEND = True
k = InStr(11, strData, "|")
sFileName = Mid$(strData, 11, k - 11)
SendFileLen = CLng(right$(strData, Len(strData) - k))
myFreeFile = FreeFile
Open sFileName For Binary As myFreeFile
End If ......... '其他程序End If
你前面给的两个代码和我自己的函数一样,都是只接受到了一部分,我把你的函数再瞧瞧。
最好编码后在传,比如用base64编码就可以
你要从上次的位置接着写
Gelim(Gelim)的程序我打印了带回去慢慢看。
至于用base64编码后再传的办法,如果 Gelim(Gelim)不怕麻烦的话,烦劳你贴来给我瞧瞧,如果方便的话我改用这个办法传。
这个月中旬就要我把项目做完,这个东西从这个月初才开始,小弟才疏学浅,光这个问题烦了我两天了,多谢各位的支持。
发这堆数据在原来文件中的偏移量(还可以加上校验字节),而接收端可以通过偏移量写到
文件中,这样的话优点是很明显的,就是结构简单,逻辑清晰,还有就是数据不会出错,即
使错了可以通过校验字节看出来后再要发送端再发一次,但这样却有个明显的缺点,那就是
速度很慢,因为它要不停的写文件,而我给你的那种方法是先写到缓冲区,然后由close一次
写到硬盘的,所以传输速度会很快!以下是base64的加解密算法:sBASE_64_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
sBASE_64_CHARACTERS = strUnicode2Ansi(sBASE_64_CHARACTERS)Function strUnicodeLen(asContents)
asContents1 = "a" & asContents
len1 = Len(asContents1)
k = 0
For i = 1 To len1
asc1 = Asc(Mid(asContents1, i, 1))
If asc1 < 0 Then asc1 = 65536 + asc1
If asc1 > 255 Then
k = k + 2
Else
k = k + 1
End If
Next
strUnicodeLen = k - 1
End FunctionFunction strUnicode2Ansi(asContents)
strUnicode2Ansi = ""
len1 = Len(asContents)
For i = 1 To len1
VarChar = Mid(asContents, i, 1)
varasc = Asc(VarChar)
If varasc < 0 Then varasc = varasc + 65536
If varasc > 255 Then
varHex = Hex(varasc)
varlow = Left(varHex, 2)
varhigh = Right(varHex, 2)
strUnicode2Ansi = strUnicode2Ansi & ChrB("&H" & varlow) & ChrB("&H" & varhigh)
Else
strUnicode2Ansi = strUnicode2Ansi & ChrB(varasc)
End If
Next
End FunctionFunction strAnsi2Unicode(asContents)
strAnsi2Unicode = ""
len1 = LenB(asContents)
If len1 = 0 Then Exit Function
For i = 1 To len1
VarChar = MidB(asContents, i, 1)
varasc = AscB(VarChar)
If varasc > 127 Then
strAnsi2Unicode = strAnsi2Unicode & Chr(AscW(MidB(asContents, i + 1, 1) & VarChar))
i = i + 1
Else
strAnsi2Unicode = strAnsi2Unicode & Chr(varasc)
End If
Next
End FunctionFunction Base64encode(asContents)
Dim lnPosition
Dim lsResult
Dim Char1
Dim Char2
Dim Char3
Dim Char4
Dim Byte1
Dim Byte2
Dim Byte3
Dim SaveBits1
Dim SaveBits2
Dim lsGroupBinary
Dim lsGroup64
Dim M4, len1, len2len1 = LenB(asContents)
If len1 < 1 Then
Base64encode = ""
Exit Function
End IfM3 = len1 Mod 3
If M3 > 0 Then asContents = asContents & String(3 - M3, ChrB(0))If M3 > 0 Then
len1 = len1 + (3 - M3)
len2 = len1 - 3
Else
len2 = len1
End IflsResult = ""For lnPosition = 1 To len2 Step 3
lsGroup64 = ""
lsGroupBinary = MidB(asContents, lnPosition, 3)Byte1 = AscB(MidB(lsGroupBinary, 1, 1)): SaveBits1 = Byte1 And 3
Byte2 = AscB(MidB(lsGroupBinary, 2, 1)): SaveBits2 = Byte2 And 15
Byte3 = AscB(MidB(lsGroupBinary, 3, 1))Char1 = MidB(sBASE_64_CHARACTERS, ((Byte1 And 252) \ 4) + 1, 1)
Char2 = MidB(sBASE_64_CHARACTERS, (((Byte2 And 240) \ 16) Or (SaveBits1 * 16) And &HFF) + 1, 1)
Char3 = MidB(sBASE_64_CHARACTERS, (((Byte3 And 192) \ 64) Or (SaveBits2 * 4) And &HFF) + 1, 1)
Char4 = MidB(sBASE_64_CHARACTERS, (Byte3 And 63) + 1, 1)
lsGroup64 = Char1 & Char2 & Char3 & Char4lsResult = lsResult & lsGroup64
NextIf M3 > 0 Then
lsGroup64 = ""
lsGroupBinary = MidB(asContents, len2 + 1, 3)Byte1 = AscB(MidB(lsGroupBinary, 1, 1)): SaveBits1 = Byte1 And 3
Byte2 = AscB(MidB(lsGroupBinary, 2, 1)): SaveBits2 = Byte2 And 15
Byte3 = AscB(MidB(lsGroupBinary, 3, 1))Char1 = MidB(sBASE_64_CHARACTERS, ((Byte1 And 252) \ 4) + 1, 1)
Char2 = MidB(sBASE_64_CHARACTERS, (((Byte2 And 240) \ 16) Or (SaveBits1 * 16) And &HFF) + 1, 1)
Char3 = MidB(sBASE_64_CHARACTERS, (((Byte3 And 192) \ 64) Or (SaveBits2 * 4) And &HFF) + 1, 1)If M3 = 1 Then
lsGroup64 = Char1 & Char2 & ChrB(61) & ChrB(61) 'ÓÃ=ºÅ²¹×ãλÊý
Else
lsGroup64 = Char1 & Char2 & Char3 & ChrB(61) 'ÓÃ=ºÅ²¹×ãλÊý
End IflsResult = lsResult & lsGroup64
End IfBase64encode = lsResultEnd Function
Function Base64decode(asContents)
Dim lsResult
Dim lnPosition
Dim lsGroup64, lsGroupBinary
Dim Char1, Char2, Char3, Char4
Dim Byte1, Byte2, Byte3
Dim M4, len1, len2len1 = LenB(asContents)
M4 = len1 Mod 4If len1 < 1 Or M4 > 0 Then
Base64decode = ""
Exit Function
End IfIf MidB(asContents, len1, 1) = ChrB(61) Then M4 = 3
If MidB(asContents, len1 - 1, 1) = ChrB(61) Then M4 = 2If M4 = 0 Then
len2 = len1
Else
len2 = len1 - 4
End IfFor lnPosition = 1 To len2 Step 4
lsGroupBinary = ""
lsGroup64 = MidB(asContents, lnPosition, 4)
Char1 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 1, 1)) - 1
Char2 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 2, 1)) - 1
Char3 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 3, 1)) - 1
Char4 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 4, 1)) - 1
Byte1 = ChrB(((Char2 And 48) \ 16) Or (Char1 * 4) And &HFF)
Byte2 = lsGroupBinary & ChrB(((Char3 And 60) \ 4) Or (Char2 * 16) And &HFF)
Byte3 = ChrB((((Char3 And 3) * 64) And &HFF) Or (Char4 And 63))
lsGroupBinary = Byte1 & Byte2 & Byte3lsResult = lsResult & lsGroupBinary
NextIf M4 > 0 Then
lsGroupBinary = ""
lsGroup64 = MidB(asContents, len2 + 1, M4) & ChrB(65) 'chr(65)=A£¬×ª»»³ÉֵΪ0
If M4 = 2 Then '²¹×ã4룬ÊÇΪÁ˱ãÓÚ¼ÆËã
lsGroup64 = lsGroup64 & ChrB(65)
End If
Char1 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 1, 1)) - 1
Char2 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 2, 1)) - 1
Char3 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 3, 1)) - 1
Char4 = InStrB(sBASE_64_CHARACTERS, MidB(lsGroup64, 4, 1)) - 1
Byte1 = ChrB(((Char2 And 48) \ 16) Or (Char1 * 4) And &HFF)
Byte2 = lsGroupBinary & ChrB(((Char3 And 60) \ 4) Or (Char2 * 16) And &HFF)
Byte3 = ChrB((((Char3 And 3) * 64) And &HFF) Or (Char4 And 63))If M4 = 2 Then
lsGroupBinary = Byte1
ElseIf M4 = 3 Then
lsGroupBinary = Byte1 & Byte2
End IflsResult = lsResult & lsGroupBinary
End IfBase64decode = lsResultEnd Function
通过你给的建议,我突然想出个新办法,定义一个静态变量,每次发生dataarrival事件的时候,都把收到的数据的大小加到这个变量上,然后在写文件的时候根据这个变量来判断写的位置,你觉得这样行不行?反正现在我还没调通,呵呵。
2、你要从发送到接收都按字节数组来进行,不要经过字符串转换
3、用SockServe.BytesReceived检查缓存里有没有剩余的字节做到这三点就可以了,不用上面那么长的代码。我刚做完一个文件传输的程序,但鉴于其复杂度要高多了,所以代码不便贴出。
Open FileName For Binary As FreeF nCnt = 1
LenFile = FileLen(FileName)
Tempstr = IIf(Right$(RemoteFilePath, 1) = "\", RemoteFilePath & _
Right$(FileName, Len(FileName) - InStrRev(FileName, "\")), RemoteFilePath & _
"\" & Right$(FileName, Len(FileName) - InStrRev(FileName, "\")))
myHead = "|FILESEND|" & Tempstr & "|" & CStr(LenFile)
WinS.SendData myHead '发送头和文件名及文件总长度!
===================================================================
这段代码明显就是把一个文件全部放到数组里然后一次过发送,这种方法我有什么可能没试过,没试过我敢说它慢吗?再来看看那个Greaitm(夜草) 说了些什么:我做的视频传输就是几k几k传的
我想问问Greaitm(夜草),你知道我在说什么吗?你自己就不是这种方法的,你驳斥我什么啊?驳斥我不就是在驳斥你自己?请看我的回贴,我已说得清清楚楚:将一个文件一次过放到数组里发送,这种方法是最不可取的,不但吃资源,发送的时候传送速度每秒只有不到1K,还不能断点续传再来看看那个Greaitm(夜草) 说了些什么:我做的视频传输就是几k几k传的大家看看,可笑吗?最搞笑的是,那个 Gelim(Gelim)居然说什么:支持Greaitm(夜草)
那么我又想问问了,Gelim(Gelim)你支持的人正好就是用了我的方法,而不是像你那样,你支持什么啊?支持个屁啊
WinS.SendData myHead '发送头和文件名及文件总长度!这两句话的意思是将数据包头"|FILESEND|" ,文件路径和文件的总长度发出去,而不是像你说的那样将整个文件发出去,大哥我的注释写得很清楚,就是不会vb的也看得出来再看:
Do Until nCnt > (LenFile)
DoEvents
If nCnt + SendDataSize - 1 > LenFile Then
ReDim LocData(LenFile - nCnt) As Byte
Else
ReDim LocData(SendDataSize - 1) As Byte
End If
Get FreeF, nCnt, LocData
WinS.SendData LocData
nCnt = nCnt + SendDataSize
objProBar.Value = objProBar.Value + 1
Loop上面这段代码才是将整个文件分成大小相等的包(长度LenFile=1024,最后一个包可能小于1024)也许,GetWindowPos(阿汪)大虾没有看清楚,这个我能理解,但至于我支持Greaitm(夜草)或者支持null1027 (营养不良的猪) 和你GetWindowPos(阿汪)有很大的关系吗?大家都是程序员,互相尊重很重要,我尊重你,也希望你能尊重我和你自己!to null1027 (营养不良的猪),我的email是[email protected],如果需要我们可以通过邮件联系!
我发的数据量比较小,并且是在局域网里,速度很快,60K的东西一秒内就可以收到,所以放到数组里一次传还是可行的,要大数据量的发送传输可以再问两位请教,但是吵架就不要了,因为我觉得好象你们二位讲的都是同样的道理,但是各自抓住自己的一方面在讲。
另外非常感谢Gelim(Gelim) 的帮忙,解决了一个对我而言很严重的技术问题,呵呵,再有问题再找你了。
谢谢。