winsock TCP 连接 批量上传下载文件

pioneer_public 2010-12-23 03:42:39
如何使用VB+winsock批量上传下载文件?

我使用WINSOCK

客户端:


Public Sub UploadFile()

Dim nUpFile As Integer
nUpFile = Me.ListView1.ListItems.Count

Dim nIndex As Integer

For nIndex = 1 To nUpFile
Me.lblNo = nIndex 'Me.ListView1.ListItems(nIndex).SubItems(0)
Me.lblLocalPath = Me.ListView1.ListItems(nIndex).SubItems(1)
Me.lblFileSize = Me.ListView1.ListItems(nIndex).SubItems(2)

Dim strFileExt As String
strFileExt = FileSystemObject.GetFileExt(Me.lblLocalPath)

'请求上传,要求服务器配文件名
Dim bSendData() As Byte
bSendData() = StrConv(WinSockInfo.C2S_REQUEST_UPLOADFILE & WinSockInfo.SAC_CONNECT_STRING & strFileExt, vbFromUnicode)
MainStart.Winsock1.SendData bSendData()
DoEvents
Next nIndex

End Sub


Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

Dim bData() As Byte
Call Me.Winsock1.GetData(bData(), vbByte, bytesTotal)

Dim strData As String
strData = StrConv(bData(), vbUnicode)
'Call Me.Winsock1.GetData(strData, , bytesTotal)

'检验是否为可识别格式
Dim nPos As Integer
nPos = InStr(strData, WinSockInfo.SAC_CONNECT_STRING)

If nPos <= 0 Then
Debug.Print "收到不明数据"
Exit Sub
End If

Dim strEventID As String
strID = Left(strData, nPos - 1)

Dim strTemp As String
strTemp = Right(strData, Len(strData) - nPos)

Select Case CInt(strID)
Case WinSockInfo.S2C_UPLOADFILE_NAME '服务器分配好上传文件名,客户端开始上传文件
frmUpload.lblRomoteFile.Caption = strTemp

'开始上传文件
Dim nSendSize As Long
Dim nFileNo As Integer
nFileNo = FreeFile

Dim bValue() As Byte

Open frmUpload.lblLocalPath For Binary Access Read As nFileNo
Dim bSendData() As Byte
Dim nFileSize As Long
nFileSize = FileLen(frmUpload.lblLocalPath)
Dim nReadSize As Integer
nReadSize = 8 * 1024 - 4 '因VB的SendData每次只能发送8K字节,否则要分包发送。同时这里的数据发送需要前后增加标记,故需减4

Dim nLastReadSize As Integer '最后一次读取字节数
nLastReadSize = nFileSize Mod nReadSize

'计算需要发送多少次
Dim nReadIndex As Long
Dim nReadCount As Long
nReadCount = nFileSize \ nReadSize
If nLastReadSize <> 0 Then
nReadCount = nReadCount + 1
End If

Dim strSendHead As String
strSendHead = WinSockInfo.C2S_UPLOADFILE & WinSockInfo.SAC_CONNECT_STRING

Dim strSendTail As String
Dim strSendData As String

For nReadIndex = 1 To nReadCount

If nReadIndex <> nReadCount Then
ReDim bValue(nReadSize - 1) As Byte
Get #nFileNo, , bValue()
Else
ReDim bValue(nLastReadSize - 1) As Byte
Get #nFileNo, , bValue()
End If

If EOF(nFileNo) = False Then
strSendTail = WinSockInfo.SAC_CONNECT_STRING & WinSockInfo.SAC_SEND_CONTINUE
Else
strSendTail = WinSockInfo.SAC_CONNECT_STRING & WinSockInfo.SAC_SEND_COMPLETE
End If

Dim strValue As String
strValue = StrConv(bValue(), vbUnicode)
strSendData = strSendHead & strValue & strSendTail
bSendData() = StrConv(strSendData, vbFromUnicode)

Me.Winsock1.SendData bSendData()
Next
Case WinSockInfo.S2C_UPLOADFILE_SIZE '服务器发来已收到文件的字节数
frmUpload.lblUpSize.Caption = strTemp
frmUpload.ProgressBar1.Value = (CLng(strTemp) * 1#) / frmUpload.lblFileSize * 100

If frmUpload.ProgressBar1.Value = 100 Then
frmUpload.Visible = False
Else
frmUpload.Visible = False
End If

Case Else

End Select

End Sub




服务器端:

Private Sub WinsockTransFile_DataArrival(Index As Integer, ByVal bytesTotal As Long)
'得到传送来的数据
Dim bGetData() As Byte
Me.WinsockTransFile(Index).GetData bGetData(), vbByte, bytesTotal

Dim strGetData As String
'Me.WinsockTransFile(Index).GetData strGetData, , bytesTotal
strGetData = StrConv(bGetData(), vbUnicode)

Dim strEvent As String
'检验是否为可识别格式
Dim nPos As Integer
nPos = InStr(strGetData, WinSockInfo.SAC_CONNECT_STRING)

Dim addWinsockInfo As WinSockInfo.WinSockInfo
Dim bSendData() As Byte
Dim strSendData As String

If nPos <= 0 Then
strEvent = "收到不明数据"
Else

Dim strEventID As String
strEventID = Left(strGetData, nPos - 1)

Dim strTemp As String
strTemp = Right(strGetData, Len(strGetData) - nPos)

Select Case CInt(strEventID)
Case WinSockInfo.C2S_SEND_COM_AND_APP ' 客户端发送计算机名及程序名
strEvent = "收到程序名"

Dim strComputerName As String
Dim strAppName As String
Dim strCallBack As String
Dim nPos2 As Integer
nPos2 = InStr(strTemp, WinSockInfo.SAC_CONNECT_STRING)

If nPos2 <= 0 Then
strCallBack = "不明数据"
Else
strComputerName = Left(strTemp, nPos2 - 1)
strAppName = Right(strTemp, Len(strTemp) - nPos2)

Me.lblClientCompName(Index) = strComputerName
Me.lblClientAppName(Index) = strAppName
End If
Case WinSockInfo.C2S_REQUEST_UPLOADFILE '请求上传文件
'计算文件名称
'Dim strFileExt As String
strFileExt = strTemp
'Dim strSaveFileName As String
strSaveFileName = Year(Now) & Month(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now)
'判断是否已存在
Dim nNo As Integer
nNo = 0
Do While FileSystemObject.IsFileExisit(Me.Label2.Caption & "\" & strSaveFileName & "." & strFileExt) = True
nNo = nNo + 1
strSaveFileName = Left(strSaveFileName, 14) & nNo
Loop
'发送最终文件名给客户端,用于显示
strEvent = "客户请求上传"
strCallBack = "文件名:" & strSaveFileName & "." & strFileExt

addWinsockInfo.strID = Me.ListView1.ListItems.Count + 1
addWinsockInfo.strIP = Me.WinsockTransFile(Index).RemoteHostIP
addWinsockInfo.strEvent = strEvent
addWinsockInfo.strTime = Year(Now) & Month(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now)
addWinsockInfo.strName = Me.lblClientCompName(Index)
addWinsockInfo.strPort = Me.WinsockListenClient(Index).RemotePort
addWinsockInfo.strProgram = Me.lblClientAppName(Index)
addWinsockInfo.strCallBack = strCallBack
Call AddListView(addWinsockInfo)

strSendData = WinSockInfo.S2C_UPLOADFILE_NAME & WinSockInfo.SAC_CONNECT_STRING & strSaveFileName
bSendData() = StrConv(strSendData, vbFromUnicode)

Me.WinsockTransFile(Index).SendData bSendData()
Exit Sub
Case WinSockInfo.C2S_UPLOADFILE '上传文件,接受数据
'取得上传标记
Dim strFlag As String
strFlag = Right(strTemp, 2)

'接收数据
Dim strWriteData As String
strWriteData = Left(strTemp, Len(strTemp) - 2)

Dim bWriteData() As Byte
bWriteData() = StrConv(strWriteData, vbFromUnicode)

'写入文件
Dim nFileNo As Integer
nFileNo = FreeFile

Dim strSaveFilePath As String
strSaveFilePath = Me.Label2.Caption & "\" & strSaveFileName & "." & strFileExt
Open strSaveFilePath For Binary Access Write As #nFileNo
Put #nFileNo, , bWriteData()
Close #nFileNo

'发送已收到字节数
Dim nRecivedFileSize As Long
nRecivedFileSize = FileLen(strSaveFilePath)

strSendData = WinSockInfo.S2C_UPLOADFILE_SIZE & WinSockInfo.SAC_CONNECT_STRING & nRecivedFileSize
bSendData() = StrConv(strSendData, vbFromUnicode)

Me.WinsockTransFile(Index).SendData bSendData()

Case Else
strEvent = "收到不明数据"
End Select
End If

addWinsockInfo.strID = Me.ListView1.ListItems.Count + 1
addWinsockInfo.strIP = Me.WinsockTransFile(Index).RemoteHostIP
addWinsockInfo.strEvent = strEvent
addWinsockInfo.strTime = Year(Now) & Month(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now)
addWinsockInfo.strName = Me.lblClientCompName(Index)
addWinsockInfo.strPort = Me.WinsockListenClient(Index).RemotePort
addWinsockInfo.strProgram = Me.lblClientAppName(Index)
addWinsockInfo.strCallBack = strCallBack
Call AddListView(addWinsockInfo)
End Sub




...全文
186 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
pioneer_public 2010-12-26
  • 打赏
  • 举报
回复
漏看了。
嗷嗷叫的老马 2010-12-26
  • 打赏
  • 举报
回复
由IsWork变量决定是否再次进入定时器内部代码.

传输开始时,IsWork为TRUE,否则为FALSE.

定时器事件中,检测到IsWork为TRUE时,就会跳出,否则扫描文件列表,将第一个不为空的文件向服务器发送,并将IsWork设置为TURE.

当文件传输完成后,清空当前文件,并设置IsWork为FLASE,则定时器就能进入文件列表扫描部分的代码,继续发送下一个文件.
pioneer_public 2010-12-26
  • 打赏
  • 举报
回复
计时器的间隔为0.1秒,为什么每次连接到服务器后,下一次的计时器启动时在文件传输完毕之后?

而且在第1个文件传输过程中,没有看到禁用计时器的代码

传输完成后,解禁计时器的代码。
pioneer_public 2010-12-26
  • 打赏
  • 举报
回复
研究了以上的代码。

为什么每个文件的传输使用了1个Winsock?

不能只使用1个Winsock来完成批量吗?

我主要是想要做一个批量上传的进度条出来,

想把这些文件通过一个Winsock来传输,并不断校验服务器已接受的数据大小,并显示进度。

而以上的代码,都是使用各自的winsock,为什么不是同步进行传输,而是一个接1个的??
嗷嗷叫的老马 2010-12-24
  • 打赏
  • 举报
回复
http://www.m5home.com/blog/article.asp?id=169

客户端上传文件到服务器端,支持多客户端,支持文件夹.

可以参考一下.
choovy123 2010-12-24
  • 打赏
  • 举报
回复
看代码的来了
pioneer_public 2010-12-24
  • 打赏
  • 举报
回复
4楼:哪里有此类工具,找了好久没有找到。

5楼:因是第1次接触winsock,没有什么资料参考,所以只能做成这样了,如果能,请指教。
startbin 2010-12-23
  • 打赏
  • 举报
回复
通讯协议太繁琐且效率不高
dbcontrols 2010-12-23
  • 打赏
  • 举报
回复
有现成的工具,就别再折腾了,浪费时间就是浪费生命
pioneer_public 2010-12-23
  • 打赏
  • 举报
回复
有API更好啊。可以学习。
gmyhbio 2010-12-23
  • 打赏
  • 举报
回复
一定要用winsock吗?
用API批量下行不?行我晚上给你帖代码。
现在在公司。
pioneer_public 2010-12-23
  • 打赏
  • 举报
回复
总的思路是:

1。 客户要求批量上传,在其中进行遍历,循环上传。首先向服务器发送数据,要求配服务器上的保存上传文件的名称

2。 服务器接到此消息,配文件名,并通知客户端新的文件名

3。 客户端在界面上显示服务器端文件名

4。根据文件的大小,循环读取数据发送给服务器端

5。服务器接到此消息,得到此数据,并写入文件中,并反通知客户端,已经获得的字节数

6。客户端在界面上显示上传进度。


问题是,在第1步时,每次循环senddata后,并没有给服务器端接收,而是几次循环结束了,才一起发送到服务器。如此只上传了1个文件,同时因数据格式的问题(因每次发送的数据都加了数据头"N|"),导致文件创建不成功。

如4个文件的后缀分别为txt,bmp,rar,xls
则服务器收到的数据位9|txt9|bmp9|rar9|xls。

请问下如何才能每次要求Senddata数据就能被服务器收到,同样服务器senddata也要每SendData一次,客户端的winsock的DataArrival时间就能响应。


或者有哪位有此类功能的代码,借阅下 :)

1,502

社区成员

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

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