




版權(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í),情況沒(méi)有那么悲觀,我們完全可以使用數(shù)組來(lái)解決這個(gè)問(wèn)題,就是使用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 '打開(kāi)文件 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開(kāi)始的,如果你寫成ReDim bytData( LenFile),下標(biāo)就是從0開(kāi)始了,數(shù)組就有LenFile+1長(zhǎng)了。LenFile = LOF(FreeFile)中的LOF是獲得文件長(zhǎng)度的函數(shù),是VB里帶的,我見(jiàn)過(guò)很多例子用API,或者循環(huán)的讀直到末尾來(lái)獲取文件長(zhǎng)度,這樣都是很麻煩的,使用LOF函數(shù)就可以了。 這樣的程序,即可以傳送文本文件,也可以傳送二進(jìn)制文件。但是你有沒(méi)有發(fā)現(xiàn)這個(gè)
6、程序的問(wèn)題呢?如果我要傳送一個(gè)50M的文件呢?系統(tǒng)可以為bytData分配50M的內(nèi)存空間嗎? 于是筆者拿一個(gè)50M的文件做實(shí)驗(yàn)吧,接收到的文件和原來(lái)的文件不一樣,比原來(lái)的大。問(wèn)題出在那呢? 首先,根據(jù)文件大小重新定義bytData數(shù)組的大小本身就有問(wèn)題,系統(tǒng)是不可能無(wú)限制的給數(shù)組分配空間的,即使可以,也會(huì)造成系統(tǒng)響應(yīng)變慢。在傳50M文件的時(shí)候,系統(tǒng)就跟死機(jī)了一樣。那么怎么解決這個(gè)問(wèn)題呢,一個(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 '打開(kāi)文件 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 '這里要注意的是,必須檢查文件有沒(méi)有剩下的數(shù)據(jù),如果文件大小正好等于數(shù)據(jù)塊大小的 ' 整數(shù)倍,那么就沒(méi)有剩下的數(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表示是第一次打開(kāi)文件,這里有個(gè)問(wèn)題,就是'如果如果該文件存在的話,就會(huì)出錯(cuò),應(yīng)該在打開(kāi)前檢查文件是否存在。(這里我省略了) 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ù)接收文件的開(kāi)關(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 '詢問(wèn)是否準(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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 生物化學(xué)(第4版)課件 第2章 核酸化學(xué)
- 氣候變化所致小島國(guó)損失損害補(bǔ)償責(zé)任問(wèn)題研究
- 基于STSE教育理念的初中化學(xué)金屬和金屬材料的教學(xué)實(shí)踐研究
- 下雨天安全教育
- 關(guān)愛(ài)婦女心理健康:現(xiàn)狀與行動(dòng)指南
- 頸椎間盤的護(hù)理課件
- 爆炸安全知識(shí)培訓(xùn)
- 人事勞資培訓(xùn)
- 項(xiàng)目管理人員安全教育培訓(xùn)
- 項(xiàng)目介紹課件模版
- 無(wú)菌技術(shù)操作評(píng)分標(biāo)準(zhǔn)
- JJG 693-2011可燃?xì)怏w檢測(cè)報(bào)警器
- 銷售行業(yè)跑業(yè)務(wù)計(jì)劃書(shū)
- 政府采購(gòu)詢價(jià)采購(gòu)函報(bào)價(jià)單格式及論大學(xué)生寫作能力
- 建筑物拆除工程監(jiān)理實(shí)施細(xì)則
- LY/T 3256-2021全國(guó)優(yōu)勢(shì)喬木樹(shù)種(組)基本木材密度測(cè)定
- GB/T 25760-2010滾動(dòng)軸承滾針和推力球組合軸承外形尺寸
- 特勞特-定位課件
- 口腔工藝管理基教學(xué)課件
- 真石漆施工外墻涂料工藝方案課件
- 2022年泰州興化市教師進(jìn)城考試筆試題庫(kù)及答案解析
評(píng)論
0/150
提交評(píng)論