用Winsock,TCP协议,传输文件时,代码如下: 'Send Private Sub CmdSend_Click() Dim myFile() As Byte Dim lngFile As Long Dim FileName As String Static i As Single FileName = VB.App.Path & "\my.gif" lngFile = FileLen(FileName) ReDim myFile(lngFile - 1) As Byte Open FileName For Binary As #1 Get #1, , myFile Close #1 WskClient.SendData myFile End Sub
'Receive Private Sub WskServer_DataArrival(Index As Integer, ByVal bytestotal As Long) Static i As Long Dim myFile() As Byte Dim myLong As Double Dim myPath As String myPath = VB.App.Path & "\my.gif" ReDim myFile(0 To bytestotal - 1) WskServer(Index).GetData myFile Open myPath For Binary As #1 Put #1, lenth + 1, myFile Close #1 lenth = lenth + UBound(myFile) - LBound(myFile) + 1 End Sub
符合那么就继续发,如果出现丢包那么就从发 希望大家有什么好的建议通知我,我会尽量完善的 Option Explicit '============================================== '=============================== 'udp传文件 '客户端 '作者: 影子 '================================ '============================================== Dim FileNumber As Integer '用来存文件的句柄 Dim LenFile As Long '文件的长度 Private Sub Command2_Click() closefile End Sub
Private Sub Form_Load() Winsock0.LocalPort = 5698 Winsock0.Bind beginfile End Sub Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long) Dim FileByte() As Byte Winsock0.GetData FileByte, vbArray + vbByte '接收类型为:字节数组 Dim mendByte() As Byte, i As Long, j As Long Dim temp As String, temp1 As String '获得包长 j = UBound(FileByte) '合并包头 For i = 0 To 7 Step 2 temp = temp & Chr(FileByte(i)) Next '比较长度看丢包没有 If Val(temp) = j Then
ReDim mendByte(j - 8) ' 提出包头 For i = 0 To j - 8 mendByte(i) = FileByte(i + 7) Next ' 写文件 Put #FileNumber, , mendByte ' 发送继续发送的请求 frmmain.Winsock0.SendData "ok" Else '出现丢包,请求重发 frmmain.Winsock0.SendData "no" End If End Sub
Public Sub beginfile() FileNumber = FreeFile '取得未使用的文件号 Open "c:\aaa.exe" For Binary As #FileNumber '打开文件 End Sub
Public Sub closefile() '关闭文件句柄 Close #FileNumber End Sub
Option Explicit Dim GetFileNum As Integer Dim LenFile As Long Dim Sendbaye() As Byte '发送的包 '=============================== 'udp传文件 '作者: 影子 '服务器端 '================================
Private Sub Command1_Click() GetFileNum = FreeFile '取得未使用的文件号 LenFile = FileLen("d:\aa.rar") '获得需传送的文件的长度 Open "d:\aa.rar" For Binary As #GetFileNum '打开需传送的文件 Command1.Enabled = False ' 传送文件 Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile) Text1.Text = Now End Sub
Private Sub Form_Load() frmmain.Winsock0.RemoteHost = "192.168.0.12" '服务器ip frmmain.Winsock0.RemotePort = 5698
End Sub '========================================================================= '为了清晰,下面分别用两个子过程来完成计算这次还可以传多少个字节的数据和传送数据 '========================================================================== Private Function SplitFile() As Long '拆包 On Error Resume Next Dim GetCount As Long '计算出这次可发送的字节数 If LenFile >= 4000 Then GetCount = 4000 LenFile = LenFile - GetCount Else GetCount = LenFile LenFile = LenFile - GetCount End If SplitFile = GetCount
End Function Private Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long) Dim FileByte() As Byte, i As Long, j As Long Dim temp As String ReDim Sendbaye(0)
Dim tempa As String * 4 ReDim FileByte(SendLen - 1) tempa = SendLen + 7 Sendbaye = tempa ' 把长度负值给包头 Get #FileNumber, , FileByte '读取文件 ReDim Preserve Sendbaye(SendLen + 7) '把包头+到文件头 For i = 0 To UBound(FileByte) Sendbaye(i + 7) = FileByte(i) Next frmmain.Winsock0.SendData Sendbaye End Sub
Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long) Dim str As String frmmain.Winsock0.GetData str Select Case str Case "ok" '成功继续发送 If LenFile = 0 Then '发送完成 MsgBox "成功" Exit Sub End If Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile) Case "no" '不成功重发上一个包 frmmain.Winsock0.SendData Sendbaye End Select End Sub
除非你修改协议,但是要收发两段都安装你修改的协议,否则无法拆包.
只是收包的时候要注意。
你可以试一下在收包代码中加debug.print bstr
会发现在调试窗口中会显示一堆数据
而这些数据就是你发送过来的数据一个小提示,可以用全局变量来存数据包,设Gstr是一个全局变量(用来暂存数据包)
那在收包的时候可用Gstr=Gstr+bstr当然上面所说的只是提示。实际运用还有点问题的。也就是发包收包要加个握手码,告诉收包的这个包已经结束了,那个全局变量可清空了。
下面是两段代码
分别是用TCP和UDP协议传送文件的
TCP不用拆包
UDP是拆包传送
两者有什么区别:
用Winsock,TCP协议,传输文件时,代码如下:
'Send
Private Sub CmdSend_Click()
Dim myFile() As Byte
Dim lngFile As Long
Dim FileName As String
Static i As Single
FileName = VB.App.Path & "\my.gif"
lngFile = FileLen(FileName)
ReDim myFile(lngFile - 1) As Byte
Open FileName For Binary As #1
Get #1, , myFile
Close #1
WskClient.SendData myFile
End Sub
'Receive
Private Sub WskServer_DataArrival(Index As Integer, ByVal bytestotal As Long)
Static i As Long
Dim myFile() As Byte
Dim myLong As Double
Dim myPath As String
myPath = VB.App.Path & "\my.gif"
ReDim myFile(0 To bytestotal - 1)
WskServer(Index).GetData myFile
Open myPath For Binary As #1
Put #1, lenth + 1, myFile
Close #1
lenth = lenth + UBound(myFile) - LBound(myFile) + 1
End Sub
上面是没有进行拆包,一次发送文件的程序,请问怎样在发送时拆包,接受时合并包?
UDP ************************************************************
Option Explicit
'==============================================
'===============================
'udp传文件
'客户端
'作者: 影子
udp传文件如何避免丢包
udp协议是1种无连接的协议,他和tcp协议比较有传输速度快,占用资源少的问题。
但是由于udp协议本身没有自动找包的功能,因此经常会出现丢包的现象,会造成传送的文件丢包的现象
因为时间匆忙和水平有限,本人在效率上没有作优化,只是简单的实现,请大家自己看源码吧
注释:
主要功能:把文件猜成4k大小的包 在包头+上包的长度 接受了1个包判断长度是否和接受的长度相符如果
符合那么就继续发,如果出现丢包那么就从发
希望大家有什么好的建议通知我,我会尽量完善的
Option Explicit
'==============================================
'===============================
'udp传文件
'客户端
'作者: 影子
'================================
'==============================================
Dim FileNumber As Integer '用来存文件的句柄
Dim LenFile As Long '文件的长度
Private Sub Command2_Click()
closefile
End Sub
Private Sub Form_Load()
Winsock0.LocalPort = 5698
Winsock0.Bind
beginfile
End Sub
Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)
Dim FileByte() As Byte
Winsock0.GetData FileByte, vbArray + vbByte '接收类型为:字节数组
Dim mendByte() As Byte, i As Long, j As Long
Dim temp As String, temp1 As String
'获得包长
j = UBound(FileByte)
'合并包头
For i = 0 To 7 Step 2
temp = temp & Chr(FileByte(i))
Next
'比较长度看丢包没有
If Val(temp) = j Then
ReDim mendByte(j - 8)
' 提出包头
For i = 0 To j - 8
mendByte(i) = FileByte(i + 7)
Next
' 写文件
Put #FileNumber, , mendByte
' 发送继续发送的请求
frmmain.Winsock0.SendData "ok"
Else
'出现丢包,请求重发
frmmain.Winsock0.SendData "no"
End If
End Sub
Public Sub beginfile()
FileNumber = FreeFile '取得未使用的文件号
Open "c:\aaa.exe" For Binary As #FileNumber '打开文件
End Sub
Public Sub closefile() '关闭文件句柄
Close #FileNumber
End Sub
Option Explicit
Dim GetFileNum As Integer
Dim LenFile As Long
Dim Sendbaye() As Byte '发送的包
'===============================
'udp传文件
'作者: 影子
'服务器端
'================================
Private Sub Command1_Click()
GetFileNum = FreeFile '取得未使用的文件号
LenFile = FileLen("d:\aa.rar") '获得需传送的文件的长度
Open "d:\aa.rar" For Binary As #GetFileNum '打开需传送的文件
Command1.Enabled = False
' 传送文件
Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)
Text1.Text = Now
End Sub
Private Sub Form_Load()
frmmain.Winsock0.RemoteHost = "192.168.0.12" '服务器ip
frmmain.Winsock0.RemotePort = 5698
End Sub
'=========================================================================
'为了清晰,下面分别用两个子过程来完成计算这次还可以传多少个字节的数据和传送数据
'==========================================================================
Private Function SplitFile() As Long '拆包
On Error Resume Next
Dim GetCount As Long
'计算出这次可发送的字节数
If LenFile >= 4000 Then
GetCount = 4000
LenFile = LenFile - GetCount
Else
GetCount = LenFile
LenFile = LenFile - GetCount
End If
SplitFile = GetCount
End Function
Private Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long)
Dim FileByte() As Byte, i As Long, j As Long
Dim temp As String
ReDim Sendbaye(0)
Dim tempa As String * 4
ReDim FileByte(SendLen - 1)
tempa = SendLen + 7
Sendbaye = tempa ' 把长度负值给包头
Get #FileNumber, , FileByte '读取文件
ReDim Preserve Sendbaye(SendLen + 7) '把包头+到文件头
For i = 0 To UBound(FileByte)
Sendbaye(i + 7) = FileByte(i)
Next
frmmain.Winsock0.SendData Sendbaye
End Sub
Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)
Dim str As String
frmmain.Winsock0.GetData str
Select Case str
Case "ok"
'成功继续发送
If LenFile = 0 Then '发送完成
MsgBox "成功"
Exit Sub
End If
Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)
Case "no"
'不成功重发上一个包
frmmain.Winsock0.SendData Sendbaye
End Select
End Sub