版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
-.z.VB中使用WinSock控件傳送文件傳送文件對于網(wǎng)絡(luò)編程來說是基本的功能,比如遠程控制軟件。在編制一個軟件時,我從網(wǎng)上下了很多傳文件的程序,這些程序提供的傳文件功能根本就不能用。傳文本還可以,傳二進制文件根本就不行。因此,作為一個基本的功能模塊,有必要單獨介紹一下。首先,在VB中要傳送字符串,你可以這樣寫:
DimstrDataAsString
strData="Test"
Winsock1.SendDatastrData
但是如果你傳送的二進制文件,你還能用String變量來存放嗎?從理論上分析是不行的,我也做了實驗,確實是不行的。文件雖然可以傳,但是接受的文件和發(fā)送的不一樣,原因可能是二進制文件里可以有任何"字符",但是不是所有的字符都可以放在String變量里。除了String類型的變量,VB中其他類型的變量都只有幾個字節(jié)長,難道一次只能發(fā)幾個字節(jié)嗎?那樣豈不是要累死機器了!其實,情況沒有則悲觀,我們完全可以使用數(shù)組來解決這個問題,就是使用byte數(shù)組。把要傳送的文件都讀到數(shù)組里,然后發(fā)送出去。程序如下:
FileName為要傳送的文件名,WinS為發(fā)送文件的WinSock控件。這是一個發(fā)送端的程序。
PublicSubSendFile(FileNameAsString,WinSAsWinsock)
DimFreeFAsInteger'空閑的文件號
DimLenFileAsLong'文件的長度
DimbytData()AsByte'存放數(shù)據(jù)的數(shù)組
FreeF=FreeFile'獲得空閑的文件號
OpenFileNameForBinaryAs*FreeFile'打開文件
DoEvents
LenFile=LOF(FreeF)'獲得文件長度
ReDimbytData(1ToLenFile)'根據(jù)文件長度重新定義數(shù)組大小
Get*FreeF,,bytData'把文件讀入到數(shù)組里
Close*FreeF'關(guān)閉文件
WinS.SendDatabytData'發(fā)送數(shù)據(jù)
EndSub
接受端的程序如下:
PrivateSubWinsock1_DataArrival(ByValbytesTotalAsLong)
DimbytData()AsByte
Dimf
f=FreeFile
OpenstrFileNameForBinaryAs*f
ReDimbytData(1TobytesTotal)
Winsock1.GetDatabytData
Put*f,i,bytData
i=i+bytesTotal'保證每次寫都是在文件的末尾,i是個全局變量
Close*f
EndSub
這里有兩個需要注意的地方,ReDimPreservebytData(1ToLenFile),下標(biāo)是從1開始的,如果你寫成ReDimbytData(LenFile),下標(biāo)就是從0開始了,數(shù)組就有LenFile+1長了。LenFile=LOF(FreeFile)中的LOF是獲得文件長度的函數(shù),是VB里帶的,我見過很多例子用API,或者循環(huán)的讀直到末尾來獲取文件長度,這樣都是很麻煩的,使用LOF函數(shù)就可以了。這樣的程序,即可以傳送文本文件,也可以傳送二進制文件。但是你有沒有發(fā)現(xiàn)這個程序的問題呢?如果我要傳送一個50M的文件呢?系統(tǒng)可以為bytData分配50M的存空間嗎?于是筆者拿一個50M的文件做實驗吧,接收到的文件和原來的文件不一樣,比原來的大。問題出在那呢?首先,根據(jù)文件大小重新定義bytData數(shù)組的大小本身就有問題,系統(tǒng)是不可能無限制的給數(shù)組分配空間的,即使可以,也會造成系統(tǒng)響應(yīng)變慢。在傳50M文件的時候,系統(tǒng)就跟死機了一樣。則怎么解決這個問題呢,一個自然的想法就是把數(shù)據(jù)分段傳送。程序如下:發(fā)送程序,iPos是個全局變量,初始值為0。這個變量保存著當(dāng)前數(shù)據(jù)的位置。ConstiMa*=65535是每個數(shù)據(jù)塊的大小。
dimiposaslong
ConstiMa*=65535
DimFreeFAsInteger'空閑的文件號
DimLenFileAsLong'文件的長度
DimbytData()AsByte'存放數(shù)據(jù)的數(shù)組
FreeF=FreeFile'獲得空閑的文件號
OpenFileNameForBinaryAs*FreeF'打開文件
DoEvents
LenFile=LOF(FreeF)'獲得文件長度
IfLenFile<=iMa*Then'如果要發(fā)送的文件小于數(shù)據(jù)塊大小,直接發(fā)送
ReDimbytData(1ToLenFile)'根據(jù)文件長度重新定義數(shù)組大小
Get*FreeF,,bytData'把文件讀入到數(shù)組里
Close*FreeF'關(guān)閉文件
WinS.SendDatabytData'發(fā)送數(shù)據(jù)
E*itSub
EndIf
'文件大于數(shù)據(jù)塊大小,進行分塊發(fā)送
DoUntil(iPos>=(LenFile-iMa*))'發(fā)送整塊數(shù)據(jù)的循環(huán)
ReDimbytData(1ToiMa*)
Get*FreeF,iPos+1,bytData
WinS.SendDatabytData
iPos=iPos+iMa*'移動iPos,使它指向下來要讀的數(shù)據(jù)
Loop
'這里要注意的是,必須檢查文件有沒有剩下的數(shù)據(jù),如果文件大小正好等于數(shù)據(jù)塊大小的
'整數(shù)倍,則就沒有剩下的數(shù)據(jù)了
ReDimbytData(1ToLenFile-iPos)'發(fā)送剩下的不夠一個數(shù)據(jù)塊的數(shù)據(jù)
Get*FreeF,iPos+1,bytData
WinS.SendDatabytData
Close*FreeF
下面是接收端的程序:
PrivateSubWinsock1_DataArrival(ByValbytesTotalAsLong)
DimbytData()AsByte
DimlLenFileAsLong
Dimf
f=FreeFile
OpenstrFileNameForBinaryAs*f'strFileName是文件名
lLenFile=LOF(f)
ReDimbytData(1TobytesTotal)
Winsock1.GetDatabytData
IflLenFile=0Then'lLenFile=0表示是第一次打開文件,這里有個問題,就是'如果如果該文件存在的話,就會出錯,應(yīng)該在打開前檢查文件是否存在。(這里我省略了)
Put*f,1,bytData
Else
Put*f,lLenFile+1,bytData
EndIf
Close*f
EndSubVBSOCKET實現(xiàn)文件傳輸支持?jǐn)帱c續(xù)傳OptionE*plicitConstPACKSIZEAsLong=65536'每包大小為64KPrivatefilepathAsStringPrivatefilenameAsStringPrivatefilelengthAsLong'存儲文件信息Privatedata()AsBytePrivatepackAsLongPrivatesendedDataAsLong'數(shù)據(jù)緩沖區(qū),文件包數(shù),已傳輸?shù)臄?shù)據(jù)PrivatealreadySendAsBooleanPrivatecmsStrAsStringConstfileDAsString="D:\NMSPlugin\source\LanBus.rar"PrivateSubcmdConnectClient_Click()WinsockSend.CloseWinsockSend.Protocol=sckTCPProtocolWinsockSend.RemoteHost=""WinsockSend.RemotePort=8080WinsockSend.Connect'連接客戶端EndSubPrivateSubcmdSendFile_Click()OpenfileDForBinaryAs*3filename="LanBus.rar"filelength=LOF(3)Close*3WinsockSend.SendData("NMSP_AYUREADY")EndSubPrivateSubWinsockSend_Connect()StatusBar1.Caption="已與客戶端建立連接。"EndSub'"發(fā)送文件"按鈕事件代碼:PrivateSubsendFile()DimiAsIntegerDimjAsLongDimmAsLongfilepath=fileDStatusBar1.Caption="向客戶端傳送文件:"&filename&"大小為:"&filelength'計算需要傳輸文件的包數(shù)pack=(filelength-sendedData)\PACKSIZEIf((filelength-sendedData)ModPACKSIZE)<>0Thenpack=pack+1EndIfIfpack=0Thenpack=pack+1EndIf'傳輸文件OpenfilepathForBinaryAs*1Fori=1Topack'如果只有一包Ifpack=1ThenDebug.Print"filename="&filename&"|filelength="&filelength&"|send="&sendedDataReDimdata(filelength-sendedData)'讀取數(shù)據(jù)Forj=sendedData+1TofilelengthGet*1,j,data(j-sendedData)Ne*t'更新已傳輸文件的數(shù)據(jù)sendedData=filelength'發(fā)送文件數(shù)據(jù)WinsockSend.SendDatadata'如果是最后一包ElseIfi+1=packThen'讀取最后一包的數(shù)據(jù)ReDimdata(filelength-sendedData)Forj=1Tofilelength-sendedDataGet*1,sendedData+j,data(j)Ne*t'發(fā)送文件數(shù)據(jù)WinsockSend.SendDatadata'更新已傳輸文件的數(shù)據(jù)sendedData=filelengthE*itForElse'將文件數(shù)據(jù)放到數(shù)據(jù)緩沖區(qū)ReDimdata(PACKSIZE)Form=1ToPACKSIZEGet*1,sendedData+m,data(j)Ne*t'發(fā)送文件數(shù)據(jù)WinsockSend.SendDatadata'更新已傳輸文件的數(shù)據(jù)sendedData=sendedData+PACKSIZEEndIfProgressBar1.Value=Int((sendedData/filelength)*100)Ne*tProgressBar1.Value=Int((sendedData/filelength)*100)Close*1alreadySend=FalseEndSub'客戶端反饋PrivateSubWinsockSend_DataArrival(ByValbytesTotalAsLong)DimcmdStrAsStringWinsockSend.GetDatacmdStr,vbStringDebug.PrintcmdStrIfMid(cmdStr,1,13)="NMSP_IAMREADY"Then'客戶端已準(zhǔn)備好接收時,要求客戶端報告已經(jīng)接收的文件大小WinsockSend.SendData"NMSP_RPTCURLE"&filenameElseIfMid(cmdStr,1,13)="NMSP_REQFILEN"Then'客戶端要求發(fā)送文件名稱WinsockSend.SendData"NMSP_FILENAME="&filenameElseIfMid(cmdStr,1,13)="NMSP_REQFILES"Then'客戶端要求發(fā)送文件大小WinsockSend.SendData"NMSP_FILESIZE="&filelength'WinsockSend.GetDatasend,vbLongElseIfMid(cmdStr,1,13)="NMSP_RECEIVED"Then'收到客戶端已經(jīng)接收到的文件大小報告Debug.Print"客戶端已經(jīng)接收了"&Mid(cmdStr,14,Len(cmdStr))sendedData=Mid(cmdStr,15,Len(cmdStr))Iffilelength=sendedDataThenWinsockSend.SendData"NMSP_SENDDONE"'初始化文件名,大小,已接收大小,遍歷是否還需要向別的客戶端發(fā)送Letfilename=""Letfilelength=0LetsendedData=0WinsockSend.CloseStatusBar1.Caption="文件發(fā)送完畢!"ElseCallsendFileEndIfEndIfEndSub'==========================================================客戶端======================================================OptionE*plicitDimflagAsBoolean'設(shè)置是否繼續(xù)接收文件的開關(guān)標(biāo)識PrivatereadyReceiveAsBooleanPrivatefilenameAsStringPrivatetempfileAsStringPrivaterealfileAsStringPrivatereveivePathAsStringPrivatefilelengthAsLong'存儲文件信息Privatedata()AsByte,receivedAsLong'聲明數(shù)據(jù)緩沖區(qū)和已接收的數(shù)據(jù)PrivateSubForm_Load()reveivePath=App.Path&"\received\"WinsockReceive.Protocol=sckTCPProtocolWinsockReceive.LocalPort=8080WinsockReceive.ListenCallinitReceiveStateEndSubPrivateSubWinsockReceive_Connect()StatusBar1.Caption="已經(jīng)連接到服務(wù)器"EndSubPrivateSubWinsockReceive_ConnectionRequest(ByValrequestIDAsLong)IfWinsockReceive.State<>0ThenWinsockReceive.CloseEndIfWinsockReceive.AcceptrequestIDStatusBar1.Caption="已接受連接請求。"EndSubPrivateSubWinsockReceive_DataArrival(ByValbytesTotalAsLong)DimjAsLong'分別接收傳輸文件的文件名、文件長度'WinsockReceive.GetDatafilename,vbString,bytesTotal-4'WinsockReceive.GetDatafilelength,vbLong'判斷指令類型IfreadyReceive=FalseThenDimcmdStrAsStringWinsockReceive.GetDatacmdStr,vbStringDebug.PrintcmdStrIfMid(cmdStr,1,13)="NMSP_AYUREADY"Then'詢問是否準(zhǔn)備好接收文件Iffilename=""ThenWinsockReceive.SendData("NMSP_REQFILEN")ElseIffilelength=0ThenWinsockReceive.SendData("NMSP_REQFILES")ElseWinsockReceive.SendData("NMSP_IAMREADY")EndIfElseIfMid(cmdStr,1,13)="NMSP_FILENAME"Then'文件名filename=Mid(cmdStr,15,Len(cmdStr))WinsockReceive.SendData("NMSP_REQFILES")ElseIfMid(cmdStr,1,13)="NMSP_FILESIZE"Then'文件大小filelength=Mid(cmdStr,15,Len(cmdStr))Debug.PrintfilelengthIf(filelength<>0)ThenWinsockReceive.SendData("NMSP_IAMREADY")EndIfElseIfMid(cmdStr,1,13)="NMSP_RPTCURLE"Then'服務(wù)器端要求提供已經(jīng)接收的文件大小'為傳輸文件設(shè)置臨時文件realfile=reveivePath&filenametempfile=reveivePath&filename&".td"'返回已接收的數(shù)據(jù)'OpenrealfileForBinaryAs*1OpentempfileForBinaryAs*2IfLOF(2)>0ThenInput*2,receivedDebug.Print"received="&receivedEndIfClose*2WinsockReceive.SendData"NMSP_RECEIVED="&receivedreadyReceive=TrueStatusBar1.Caption="準(zhǔn)備接收文件:"&filename&"大小為:"&filelengthElseIfMid(cmdStr,1,14)="NMSP_SENDDONE="Then'服務(wù)器發(fā)送文件完畢執(zhí)行安裝操作EndIfElserealfile=reveivePath&filenametempfile=reveivePath&filename&".
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中國禮儀課件教學(xué)課件
- 開學(xué)課件模板教學(xué)課件
- 灌腸護理課件教學(xué)課件
- 2024年農(nóng)用搬運機械項目資金籌措計劃書代可行性研究報告
- 精神病醫(yī)院藥劑科相關(guān)
- 3.2.3酸堿中和滴定 課件高二上學(xué)期化學(xué)人教版(2019)選擇性必修1
- DB1304T 480-2024商品煤采樣技術(shù)規(guī)范
- 社團的活動部部門介紹
- 靜脈輸液治療在臨床中的應(yīng)用
- 白血病飲食宣教
- 近視防控主題班會PPT課件
- 三通道視景及三維態(tài)勢仿真系統(tǒng)中端方案
- 內(nèi)鏡中心進修護士培訓(xùn)計劃
- 深圳市不動產(chǎn)登記申請表
- 裝修垃圾清運單
- (精心整理)整體認(rèn)讀音節(jié)練習(xí)
- 車位委托經(jīng)營管理協(xié)議
- 三相步進電機控制程序及電路
- 硬筆書法課教學(xué)(課堂PPT)
- 焊 接 與 切 割 安 全
- 焊接吊耳及設(shè)計計算及正確使用方法
評論
0/150
提交評論