傳送檔案對於網路程式設計來說是基本的功能,比如遠端控制軟體。在編制乙個軟體時,我從網上下了很多傳檔案的程式,這些程式提供的傳檔案功能根本就不能用。傳文字還可以,傳二進位制檔案根本就不行。因此,作為乙個基本的功能模組,有必要單獨介紹一下。
首先,在vb中要傳送字串,你可以這樣寫:
dim strdata as string
strdata = "test"
winsock1.senddata strdata
但是如果你傳送的二進位制檔案,你還能用string變數來存放嗎?從理論上分析是不行的,我也做了實驗,確實是不行的。檔案雖然可以傳,但是接受的檔案和傳送的不一樣,原因可能是二進位制檔案裡可以有任何"字元",但是不是所有的字元都可以放在string變數裡。
除了string型別的變數,vb中其他型別的變數都只有幾個位元組長,難道一次只能發幾個位元組嗎?那樣豈不是要累死機器了!其實,情況沒有那麼悲觀,我們完全可以使用陣列來解決這個問題,就是使用byte陣列。把要傳送的檔案都讀到陣列裡,然後傳送出去。程式如下:
filename 為要傳送的檔名,wins為傳送檔案的winsock控制項。這是乙個傳送端的程式。
public sub sendfile(filename as string, wins as winsock)
dim freef as integer '空閒的檔案號
dim lenfile as long '檔案的長度
dim bytdata() as byte '存放資料的陣列
freef = freefile '獲得空閒的檔案號
open filename for binary as #freefile '開啟檔案
doevents
lenfile = lof(freefile) '獲得檔案長度
redim bytdata(1 to lenfile) '根據檔案長度重新定義陣列大小
get #freefile, , bytdata '把檔案讀入到陣列裡
close #freefile '關閉檔案
wins.senddata bytdata '傳送資料
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 + bytestotal '保證每次寫都是在檔案的末尾, i是個全域性變數
close #f
end sub
這裡有兩個需要注意的地方,redim preserve bytdata(1 to lenfile),下標是從1開始的,如果你寫成redim bytdata( lenfile),下標就是從0開始了,陣列就有lenfile+1長了。lenfile = lof(freefile)中的lof是獲得檔案長度的函式,是vb裡帶的,我見過很多例子用api,或者迴圈的讀直到末尾來獲取檔案長度,這樣都是很麻煩的,使用lof函式就可以了。
這樣的程式,即可以傳送文字檔案,也可以傳送二進位制檔案。但是你有沒有發現這個程式的問題呢?如果我要傳送乙個50m的檔案呢?系統可以為bytdata分配50m的記憶體空間嗎?
於是筆者拿乙個50m的檔案做實驗吧,接收到的檔案和原來的檔案不一樣,比原來的大。問題出在那呢?
首先,根據檔案大小重新定義bytdata陣列的大小本身就有問題,系統是不可能無限制的給陣列分配空間的,即使可以,也會造成系統響應變慢。在傳50m檔案的時候,系統就跟宕機了一樣。那麼怎麼解決這個問題呢,乙個自然的想法就是把資料分段傳送。程式如下:
傳送程式, ipos是個全域性變數,初始值為0。這個變數儲存著當前資料的位置。const imax = 65535是每個資料塊的大小。
dim freef as integer '空閒的檔案號
dim lenfile as long '檔案的長度
dim bytdata() as byte '存放資料的陣列
freef = freefile '獲得空閒的檔案號
open filename for binary as #freef '開啟檔案
doevents
lenfile = lof(freef) '獲得檔案長度
if lenfile <= imax then '如果要傳送的檔案小於資料塊大小,直接傳送
redim bytdata(1 to lenfile) '根據檔案長度重新定義陣列大小
get #freef, , bytdata '把檔案讀入到陣列裡
close #freef '關閉檔案
wins.senddata bytdata '傳送資料
exit sub
end if
'檔案大於資料塊大小,進行分塊傳送
do until (ipos >= (lenfile - imax)) '傳送整塊資料的迴圈
redim bytdata(1 to imax)
get #freef, ipos + 1, bytdata
wins.senddata bytdata
ipos = ipos + imax '移動ipos,使它指向下來要讀的資料
loop
'這裡要注意的是,必須檢查檔案有沒有剩下的資料,如果檔案大小正好等於資料塊大小的
' 整數倍,那麼就沒有剩下的資料了
redim bytdata(1 to lenfile - ipos) '傳送剩下的不夠乙個資料塊的資料
get #freef, ipos + 1, bytdata
wins.senddata bytdata
close #freef
下面是接收端的程式:
private sub winsock1_dataarrival(byval bytestotal as long)
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表示是第一次開啟檔案,這裡有個問題,就是'如果如果該檔案存在的話,就會出錯,應該在開啟前檢查檔案是否存在。(這裡我省略了)
put #f, 1, bytdata
else
put #f, llenfile + 1, bytdata
end if
close #f
end sub
VB中使用WinSock控制項傳送檔案
傳送檔案對於網路程式設計來說是基本的功能,比如遠端控制軟體。在編制乙個軟體時,我從網上下了很多傳檔案的程式,這些程式提供的傳檔案功能根本就不能用。傳文字還可以,傳二進位制檔案根本就不行。因此,作為乙個基本的功能模組,有必要單獨介紹一下。首先,在vb中要傳送字串,你可以這樣寫 dim strdata ...
請教在 VFP 中使用 winsock 控制項的問題
我在vfp中用winsock控制項開發乙個與微控制器通訊的程式,接收微控制器中儲存的資料。該控制項的dataarrival事件中主要 但發現微控制器發來的資料中凡ascii碼小於128的都可正常接收,大於128的字元如果成對出現 例如漢字 也可以正常接收。但如果不成對就會出現異常,例如微控制器發出的...
VB報表設計中使用天宇報表控制項
報表是軟體開發過程中非常耗費精力的事。並且報表的要求又很高。在我們試用了大量的專業報表工具如天宇報表 crystal reports 之後,我和我朋友對如何將這個複雜的東東加入我們的報表應用中有著非常的好奇心,但後來越來越感覺它的複雜程度不易使我們激動,且靈活性令人無法敬慕,久於久之,我們就有了開發...