線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1224
推到 Plurk!
推到 Facebook!

Delphi編寫點對點傳文件程序

尚未結案
Kenlin2004
一般會員


發表:20
回覆:33
積分:10
註冊:2004-10-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-04-12 11:39:41 IP:61.30.xxx.xxx 未訂閱
Delphi功能強大,用Delphi寫軟件,可以大大縮短軟件的開發週期。我們利用Delphi中TServerSocket和TClientSocket寫這個程序由於以太包大小的限制以及DelphiSocket的處理機制(Delphi中,當你用一個Socket發送一個較大的Stream,接受方會激發多次OnRead事件,Delphi她只保證多次OnRead事件中每次數據的完整,而不會自己收集數據並返回給用戶。所以不要以為你把待傳文件在一個Socket中Send一次,另一個中Recv一次就可以了。你必須自己收集數據或自己定義協議。),所以我們採用自定義協議的方法。定義協議的規範方法是利用Record End。如: TMyFileProtocol=Record sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...); iLength:integer; bufSend:Buffer; End; 我曾試過這個辦法,但失敗了,而且我一直認為我的方法是正確的,但程序一直編譯通不過,估計是Delphi有問題:) 所以我在下列的範例程序中利用另外一種辦法。Socket 類中有兩屬性ReceiveText和ReceiveBuf,在一個OnRead事件中,只能使用一次該兩屬性,所以我們可以利用一個全程變量來保存是該讀Text還是Buf,也就是說讀一次Text,再都一次Buf,這就模擬了TMyFileProtocol。 開始程序: 寫一個最簡單的,主要用於講解方法。 定義協議: Const MP_QUERY ='1'; MP_REFUSE ='2'; MP_ACCEPT ='3'; MP_NEXTWILLBEDATA='4'; MP_DATA ='5'; MP_ABORT ='6'; MP_OVER ='7'; MP_CHAT ='8'; 協議簡介: 首先由Client發送MP_QUERY,Server接受到後發送MP_ACCEPT或MP_FEFUESE; Client接受到MP_ACCEPT發送MP_FILEPROPERTY,Server接受到後發送MP_NEXTWILLBEDATA; Client接受到發送MP_NEXTWILLBEDATA,Server接受到後發送MP_DATA; Client接受到MP_DATA,發送數據,Server接受數據,並發送MP_NEXTWILLBEDATA; 循環,直到Client發送MP_OVER; 中間可以互相發送MP_CHAT String; Server程序: 放上以下控件:SaveDialog1,btnStartServer, ss,(TServerSocket) btnStartServer.OnClick(Sender:TObject); begin ss.Port:=2000; ss.Open; end; ss.OnClientRead(Sender: TObject;Socket: TCustomWinSocket); var sTemp:string; bufRecv:Pointer; iRecvLength:integer; begin if bReadText then begin sTemp:=Socket.ReceiveText; case sTemp[1] of MP_QUERY:begin //在這裡拒絕 SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp)); if SaveDialog1.Execute then begin Socket.SendText(MP_ACCEPT); fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate); end else Socket.SendText(MP_REFUSE '去死'); end; MP_FILEPROPERTY:begin //要發送StrToInt(Copy(sTemp,2,Length(sTemp))) 次 //時間進度顯示。。。 Socket.SendText(MP_NEXTWILLBEDATA); end; MP_NEXTWILLBEDATA:begin Socket.SendText(MP_DATA); bReadText:=false; end; MP_END:begin fsRecv.Free bReadText:=true; end; MP_ABORT:begin fsRecv.Free; bReadText:=true; end; MP_CHAT:begin //Chat Msg end; end;{of case} end else begin try GetMem(bufRecv,2000);//2000 must >iBYTESEND Socket.ReceiveBuf(bufRecv^,iRecvLength); fsRecv.WriteBuffer(bufRecv^,iRecvLength); finally FreeMem(bufRecv,2000); end;{of try} bReadText:=true; Socket.SendText(MP_NEXTWILLBEDATA); end; end; Client程序: 放上以下控件:edtIPAddress,OpenDialog1,btnConnect,btnSendFile, cs. (TClientSocket) btnConnect.OnClick(Sender:TObject); begin cs.Address:=edtIPAddress.Text; cs.Port:=2000; cs.Connect; end; btnSendFile.OnClick(Sender:TObject); begin if OpenDialog1.Execute then Begin cs.Socket.SendText(MP_QUERY OpenDialog1.FileName);//FileSize??? end; end; cs.OnRead(Sender: TObject;Socket: TCustomWinSocket); var sTemp:string; bufSend:pointer; begin sRecv:=Socket.ReceiveText; Case sRecv[1] of MP_REFUSE:ShowMessage('Faint,be refused!'); MP_ACCEPT:begin fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpen); //iBYTEPERSEND是個常量,每次發送包的大小。 Socket.SendText(MP_FILEPROPERTY Trunc(fsSend.Size/iBYTEPERSEND) 1); end; MP_NEXTWILLBEDATA:begin Socket.SendText(MP_NEXTWILLBEDATA); end; MP_DATA:begin try GetMem(bufSend,iBYTEPERSEND 1); if (fsSend.Position 1 iBYTEPERSEND) < fsSend.Size then begin fsSend.Read(bufSend^,iBYTEPERSEND); Socket.SendBuf(bufSend^,iBYTEPERSEND); fsSend.Free; end//普通的發送,大小為iBYTEPERSEND else begin fsSend.Read(bufSend^,fsSend.Size-fsSend.Position-1); Socket.SendBuf(bufSend^,fsSend.Size-fsSend.Position-1); end;//最後一次發送,發送剩餘的數據 finally FreeMem(bufSend,iBYTEPERSEND 1); end;{of try} end; MP_ABORT:begin //被取消了:( fsSend.Free; end; end;{of case} end; 整理程序: 加入錯誤判斷,優化程序,把Server和Client聯合在一起,加入剩餘時間進度顯示,做成能一次傳多個文件,加入聊天功能,就成了一個很好的點對點傳文件的程序。 ====================================== 技術是追不完地,量力而為! ======================================
Ktop_Robot
站務副站長


發表:0
回覆:3511
積分:0
註冊:2007-04-17

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-04-26 13:50:58 IP:000.000.xxx.xxx 未訂閱
提問者您好:


以上回應是否已得到滿意的答覆?


若已得到滿意的答覆,請在一週內結案,否則請在一週內回覆還有什麼未盡事宜,不然,
將由版主(尚無版主之區域將由副站長或站長)自由心證,選擇較合適之解答予以結案處理,
被選上之答題者同樣會有加分獎勵同時發問者將受到扣 1 分的處分。不便之處,請見諒。


有問有答有結案,才能有良性的互動,良好的討論環境需要大家共同維護,感謝您的配合。

------
我是機器人,我不接受簡訊.
系統時間:2024-05-12 2:21:11
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!