




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、VB中使用WinSock控件傳送文件 傳送文件對(duì)于網(wǎng)絡(luò)編程來(lái)說(shuō)是基本的功能,比如遠(yuǎn)程控制軟件。在編制一個(gè)軟件時(shí),我從網(wǎng)上下了很多傳文件的程序,這些程序提供的傳文件功能根本就不能用。傳文本還可以,傳二進(jìn)制文件根本就不行。因此,作為一個(gè)基本的功能模塊,有必要單獨(dú)介紹一下。 首先,在VB中要傳送字符串,你可以這樣寫: Dim strData As String strData = "Test" Winsock1.SendData strData 但是如果你傳送的二進(jìn)制文件,你還能用String變量來(lái)存放嗎?從理論上分析是不行的,我也做了實(shí)驗(yàn),確實(shí)是不行的。文件雖然可以傳,但是接受
2、的文件和發(fā)送的不一樣,原因可能是二進(jìn)制文件里可以有任何"字符",但是不是所有的字符都可以放在String變量里。 除了String類型的變量,VB中其他類型的變量都只有幾個(gè)字節(jié)長(zhǎng),難道一次只能發(fā)幾個(gè)字節(jié)嗎?那樣豈不是要累死機(jī)器了!其實(shí),情況沒有那么悲觀,我們完全可以使用數(shù)組來(lái)解決這個(gè)問題,就是使用byte數(shù)組。把要傳送的文件都讀到數(shù)組里,然后發(fā)送出去。程序如下: FileName 為要傳送的文件名,WinS為發(fā)送文件的WinSock控件。這是一個(gè)發(fā)送端的程序。 Public Sub SendFile(FileName As String, WinS As Winsock)
3、Dim FreeF As Integer '空閑的文件號(hào) Dim LenFile As Long '文件的長(zhǎng)度 Dim bytData() As Byte '存放數(shù)據(jù)的數(shù)組 FreeF = FreeFile '獲得空閑的文件號(hào) Open FileName For Binary As #FreeFile '打開文件 DoEvents LenFile = LOF(FreeF) '獲得文件長(zhǎng)度 ReDim bytData(1 To LenFile) '根據(jù)文件長(zhǎng)度重新定義數(shù)組大小 Get #FreeF, , bytData '把文件讀入
4、到數(shù)組里 Close #FreeF '關(guān)閉文件 WinS.SendData bytData '發(fā)送數(shù)據(jù) End Sub 接受端的程序如下: Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim bytData() As Byte Dim f f = FreeFile Open strFileName For Binary As #f ReDim bytData(1 To bytesTotal) Winsock1.GetData bytData Put #f, i, bytData i = i + bytes
5、Total '保證每次寫都是在文件的末尾, i是個(gè)全局變量 Close #f End Sub 這里有兩個(gè)需要注意的地方,ReDim Preserve bytData(1 To LenFile),下標(biāo)是從1開始的,如果你寫成ReDim bytData( LenFile),下標(biāo)就是從0開始了,數(shù)組就有LenFile+1長(zhǎng)了。LenFile = LOF(FreeFile)中的LOF是獲得文件長(zhǎng)度的函數(shù),是VB里帶的,我見過(guò)很多例子用API,或者循環(huán)的讀直到末尾來(lái)獲取文件長(zhǎng)度,這樣都是很麻煩的,使用LOF函數(shù)就可以了。 這樣的程序,即可以傳送文本文件,也可以傳送二進(jìn)制文件。但是你有沒有發(fā)現(xiàn)這個(gè)
6、程序的問題呢?如果我要傳送一個(gè)50M的文件呢?系統(tǒng)可以為bytData分配50M的內(nèi)存空間嗎? 于是筆者拿一個(gè)50M的文件做實(shí)驗(yàn)吧,接收到的文件和原來(lái)的文件不一樣,比原來(lái)的大。問題出在那呢? 首先,根據(jù)文件大小重新定義bytData數(shù)組的大小本身就有問題,系統(tǒng)是不可能無(wú)限制的給數(shù)組分配空間的,即使可以,也會(huì)造成系統(tǒng)響應(yīng)變慢。在傳50M文件的時(shí)候,系統(tǒng)就跟死機(jī)了一樣。那么怎么解決這個(gè)問題呢,一個(gè)自然的想法就是把數(shù)據(jù)分段傳送。程序如下: 發(fā)送程序, iPos是個(gè)全局變量,初始值為0。這個(gè)變量保存著當(dāng)前數(shù)據(jù)的位置。Const iMax = 65535是每個(gè)數(shù)據(jù)塊的大小。 dim ipos as lo
7、ngConst iMax = 65535Dim FreeF As Integer '空閑的文件號(hào) Dim LenFile As Long '文件的長(zhǎng)度 Dim bytData() As Byte '存放數(shù)據(jù)的數(shù)組 FreeF = FreeFile '獲得空閑的文件號(hào) Open FileName For Binary As #FreeF '打開文件 DoEvents LenFile = LOF(FreeF) '獲得文件長(zhǎng)度 If LenFile <= iMax Then '如果要發(fā)送的文件小于數(shù)據(jù)塊大小,直接發(fā)送 ReDim bytD
8、ata(1 To LenFile) '根據(jù)文件長(zhǎng)度重新定義數(shù)組大小 Get #FreeF, , bytData '把文件讀入到數(shù)組里 Close #FreeF '關(guān)閉文件 WinS.SendData bytData '發(fā)送數(shù)據(jù) Exit Sub End If '文件大于數(shù)據(jù)塊大小,進(jìn)行分塊發(fā)送 Do Until (iPos >= (LenFile - iMax) '發(fā)送整塊數(shù)據(jù)的循環(huán) ReDim bytData(1 To iMax) Get #FreeF, iPos + 1, bytData WinS.SendData bytData iP
9、os = iPos + iMax '移動(dòng)iPos,使它指向下來(lái)要讀的數(shù)據(jù) Loop '這里要注意的是,必須檢查文件有沒有剩下的數(shù)據(jù),如果文件大小正好等于數(shù)據(jù)塊大小的 ' 整數(shù)倍,那么就沒有剩下的數(shù)據(jù)了 ReDim bytData(1 To LenFile - iPos) '發(fā)送剩下的不夠一個(gè)數(shù)據(jù)塊的數(shù)據(jù) Get #FreeF, iPos + 1, bytData WinS.SendData bytData Close #FreeF 下面是接收端的程序: Private Sub Winsock1_DataArrival(ByVal bytesTotal As Lo
10、ng) Dim bytData() As Byte Dim lLenFile As Long Dim f f = FreeFile Open strFileName For Binary As #f 'strFileName是文件名 lLenFile = LOF(f) ReDim bytData(1 To bytesTotal) Winsock1.GetData bytData If lLenFile = 0 Then 'lLenFile=0表示是第一次打開文件,這里有個(gè)問題,就是'如果如果該文件存在的話,就會(huì)出錯(cuò),應(yīng)該在打開前檢查文件是否存在。(這里我省略了) Put
11、 #f, 1, bytData Else Put #f, lLenFile + 1, bytData End If Close #f End SubVB SOCKET 實(shí)現(xiàn)文件傳輸 支持?jǐn)帱c(diǎn)續(xù)傳Option ExplicitConst PACKSIZE As Long = 65536 '每包大小為64KPrivate filepath As StringPrivate filename As StringPrivate filelength As Long '存儲(chǔ)文件信息Private data() As BytePrivate pack As LongPrivate send
12、edData As Long '數(shù)據(jù)緩沖區(qū),文件包數(shù),已傳輸?shù)臄?shù)據(jù)Private alreadySend As BooleanPrivate cmsStr As StringConst fileD As String = "D:NMSPluginsourceLanBus.rar"Private Sub cmdConnectClient_Click() WinsockSend.Close WinsockSend.Protocol = sckTCPProtocol WinsockSend.RemoteHost = "" Winsoc
13、kSend.RemotePort = 8080 WinsockSend.Connect '連接客戶端End SubPrivate Sub cmdSendFile_Click() Open fileD For Binary As #3 filename = "LanBus.rar" filelength = LOF(3) Close #3 WinsockSend.SendData ("NMSP_AYUREADY")End SubPrivate Sub WinsockSend_Connect() StatusBar1.Caption = "
14、已與客戶端建立連接。"End Sub'"發(fā)送文件"按鈕事件代碼:Private Sub sendFile() Dim i As Integer Dim j As Long Dim m As Long filepath = fileD StatusBar1.Caption = "向客戶端傳送文件:" & filename & " 大小為:" & filelength '計(jì)算需要傳輸文件的包數(shù) pack = (filelength - sendedData) PACKSIZE If (fi
15、lelength - sendedData) Mod PACKSIZE) <> 0 Then pack = pack + 1 End If If pack = 0 Then pack = pack + 1 End If '傳輸文件 Open filepath For Binary As #1 For i = 1 To pack '如果只有一包 If pack = 1 Then Debug.Print "filename=" & filename & " | filelength=" & fileleng
16、th & " | send=" & sendedData ReDim data(filelength - sendedData) '讀取數(shù)據(jù) For j = sendedData + 1 To filelength Get #1, j, data(j - sendedData) Next '更新已傳輸文件的數(shù)據(jù) sendedData = filelength'發(fā)送文件數(shù)據(jù) WinsockSend.SendData data '如果是最后一包 ElseIf i + 1 = pack Then '讀取最后一包的數(shù)據(jù) ReD
17、im data(filelength - sendedData) For j = 1 To filelength - sendedData Get #1, sendedData + j, data(j) Next '發(fā)送文件數(shù)據(jù) WinsockSend.SendData data '更新已傳輸文件的數(shù)據(jù) sendedData = filelength Exit For Else '將文件數(shù)據(jù)放到數(shù)據(jù)緩沖區(qū) ReDim data(PACKSIZE) For m = 1 To PACKSIZE Get #1, sendedData + m, data(j) Next
18、9;發(fā)送文件數(shù)據(jù) WinsockSend.SendData data '更新已傳輸文件的數(shù)據(jù) sendedData = sendedData + PACKSIZE End If ProgressBar1.Value = Int(sendedData / filelength) * 100) Next ProgressBar1.Value = Int(sendedData / filelength) * 100) Close #1 alreadySend = False End Sub'客戶端反饋Private Sub WinsockSend_DataArrival(ByVal
19、bytesTotal As Long) Dim cmdStr As String WinsockSend.GetData cmdStr, vbString Debug.Print cmdStr If Mid(cmdStr, 1, 13) = "NMSP_IAMREADY" Then '客戶端已準(zhǔn)備好接收時(shí),要求客戶端報(bào)告已經(jīng)接收的文件大小 WinsockSend.SendData "NMSP_RPTCURLE" & filename ElseIf Mid(cmdStr, 1, 13) = "NMSP_REQFILEN"
20、 Then '客戶端要求發(fā)送文件名稱 WinsockSend.SendData "NMSP_FILENAME=" & filename ElseIf Mid(cmdStr, 1, 13) = "NMSP_REQFILES" Then '客戶端要求發(fā)送文件大小 WinsockSend.SendData "NMSP_FILESIZE=" & filelength 'WinsockSend.GetData send, vbLong ElseIf Mid(cmdStr, 1, 13) = "N
21、MSP_RECEIVED" Then '收到客戶端已經(jīng)接收到的文件大小報(bào)告 Debug.Print "客戶端已經(jīng)接收了 " & Mid(cmdStr, 14, Len(cmdStr) sendedData = Mid(cmdStr, 15, Len(cmdStr) If filelength = sendedData Then WinsockSend.SendData "NMSP_SENDDONE" '初始化文件名,大小,已接收大小,遍歷是否還需要向別的客戶端發(fā)送 Let filename = ""
22、Let filelength = 0 Let sendedData = 0 WinsockSend.Close StatusBar1.Caption = "文件發(fā)送完畢!" Else Call sendFile End If End IfEnd Sub'= 客戶端 =Option ExplicitDim flag As Boolean '設(shè)置是否繼續(xù)接收文件的開關(guān)標(biāo)識(shí)Private readyReceive As BooleanPrivate filename As StringPrivate tempfile As StringPrivate realfi
23、le As StringPrivate reveivePath As StringPrivate filelength As Long '存儲(chǔ)文件信息Private data() As Byte, received As Long '聲明數(shù)據(jù)緩沖區(qū)和已接收的數(shù)據(jù)Private Sub Form_Load() reveivePath = App.Path & "received" WinsockReceive.Protocol = sckTCPProtocol WinsockReceive.LocalPort = 8080 WinsockReceive
24、.Listen Call initReceiveStateEnd SubPrivate Sub WinsockReceive_Connect() StatusBar1.Caption = "已經(jīng)連接到服務(wù)器"End SubPrivate Sub WinsockReceive_ConnectionRequest(ByVal requestID As Long) If WinsockReceive.State <> 0 Then WinsockReceive.Close End If WinsockReceive.Accept requestID StatusBar
25、1.Caption = "已接受連接請(qǐng)求。"End SubPrivate Sub WinsockReceive_DataArrival(ByVal bytesTotal As Long) Dim j As Long '分別接收傳輸文件的文件名、文件長(zhǎng)度 'WinsockReceive.GetData filename, vbString, bytesTotal - 4 'WinsockReceive.GetData filelength, vbLong '判斷指令類型 If readyReceive = False Then Dim cmdS
26、tr As String WinsockReceive.GetData cmdStr, vbString Debug.Print cmdStr If Mid(cmdStr, 1, 13) = "NMSP_AYUREADY" Then '詢問是否準(zhǔn)備好接收文件 If filename = "" Then WinsockReceive.SendData ("NMSP_REQFILEN") ElseIf filelength = 0 Then WinsockReceive.SendData ("NMSP_REQFILES&
27、quot;) Else WinsockReceive.SendData ("NMSP_IAMREADY") End If ElseIf Mid(cmdStr, 1, 13) = "NMSP_FILENAME" Then '文件名 filename = Mid(cmdStr, 15, Len(cmdStr) WinsockReceive.SendData ("NMSP_REQFILES") ElseIf Mid(cmdStr, 1, 13) = "NMSP_FILESIZE" Then '文件大小 f
28、ilelength = Mid(cmdStr, 15, Len(cmdStr) Debug.Print filelength If (filelength <> 0) ThenWinsockReceive.SendData ("NMSP_IAMREADY") End If ElseIf Mid(cmdStr, 1, 13) = "NMSP_RPTCURLE" Then '服務(wù)器端要求提供已經(jīng)接收的文件大小 '為傳輸文件設(shè)置臨時(shí)文件 realfile = reveivePath & filename tempfile =
29、 reveivePath & filename & ".td" '返回已接收的數(shù)據(jù) 'Open realfile For Binary As #1 Open tempfile For Binary As #2 If LOF(2) > 0 Then Input #2, received Debug.Print "received=" & received End If Close #2 WinsockReceive.SendData "NMSP_RECEIVED=" & received readyReceive = True StatusBar1.Caption = "準(zhǔn)備接收文件:" & filename & " 大小為:" & filelength ElseIf Mid(cmdStr, 1, 14) = "NMSP_SENDDONE=" Then '服務(wù)器發(fā)送文件完畢 執(zhí)行 安裝操作 End If Else realfile = reveivePath &
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 租房產(chǎn)土地合同協(xié)議書
- 員工無(wú)工資試用協(xié)議書
- 職校就業(yè)協(xié)議書
- 藝術(shù)簽名協(xié)議書
- 水產(chǎn)車出售轉(zhuǎn)讓協(xié)議書
- 資產(chǎn)轉(zhuǎn)租協(xié)議書
- 貨車轉(zhuǎn)賣協(xié)議書
- 配音合作協(xié)議書
- 租貸委托協(xié)議書
- 村委會(huì)簽訂合作協(xié)議書
- 2025年山東省聊城市高唐縣中考二模英語(yǔ)試題(原卷版+解析版)
- 企業(yè)數(shù)字化轉(zhuǎn)型培訓(xùn)課件
- 2025屆高考語(yǔ)文押題作文及題目(9篇)
- 2025年中國(guó)白楊樹市場(chǎng)現(xiàn)狀分析及前景預(yù)測(cè)報(bào)告
- 2025年廣東省中考地理模擬試卷(含答案)
- 2025-2030年力控玩具項(xiàng)目投資價(jià)值分析報(bào)告
- 駕駛員心理試題及答案
- 北京開放大學(xué)2025年《企業(yè)統(tǒng)計(jì)》形考作業(yè)2答案
- 直播電商基礎(chǔ)試題及答案
- 人工智能在醫(yī)療領(lǐng)域應(yīng)用知識(shí)測(cè)試卷及答案
- 《實(shí)驗(yàn)室認(rèn)可培訓(xùn)》課件
評(píng)論
0/150
提交評(píng)論