Delphi实例分析:远程传输数据和文件
在Windows操作系統的平臺上,WinSock是首選的網絡編程接口,用于在網絡上傳輸數據和交換信息,它構成了Windows操作系統進行網絡編程的基礎。對于編寫網絡應用程序來說,WinSock是一門非常重要的并且必須掌握的知識,雖然現在有很多的工具如FTP程序可以在網絡上傳輸數據和文件,但是通過WinSock編程具有更大的靈活性,因為它不需要關心網絡連接的細節問題。然而用WinSock編程卻相當復雜,但是在Delphi中我們并不需要直接與WinSock的API函數打交道,因在Delphi中的TClientSocket組件和TServerSocket組件封裝了WinSock的大部分API函數,使得對WinSock的編程大大簡化。在網絡通信協議的面向連接服務中,進行傳輸數據和交換信息之前,通信雙方應該建立一條用于進行數據交換的“鏈路”,通信雙方就是利用這個“鏈路”進行穩定可靠的數據傳輸,由于建立通信的雙方都處于收發信息的狀態,并且保證了數據傳輸的穩定性,所以在傳輸較大的文件時,具有較高的效率。而建立“鏈路”和斷掉“鏈路”都需要消耗一定的時間,所以在傳輸較小文件時的效率是比較低的。
在這里我們將了解winsock如何實現遠程傳輸數據和文件。在一個局域網內不同的計算機上分別運行服務器端程序和客戶端程序。服務器端運行后就啟動,socket將建立偵聽狀態。客戶端運行后,在客戶端程序中填寫服務器IP地址,然后單擊“連接”按鈕,向服務器端發出一個建立連接的請求,如圖1所示。如果通客戶端程序過端口成功和服務器端連接,服務器端的狀態欄就會有“已和客戶端連接”的提示,并準備傳輸文件,如圖2所示。
圖1
圖2
單擊“發送”按鈕,在彈出的對話框中選擇一個準備發送的文件,然后客戶端將文件的大小和其他信息等發送到服務器端,服務器端接受到文件的信息后通知客戶端開始傳送文件,文件的數據需要多次傳遞,服務器將文件全部接受并保存。系統運行如圖3、圖4所示:
圖3
圖4
服務器端程序編寫:
新建一個項目,并把一個TServerSocket組件放到Form1窗體上,Active設為True;端口Port設為2000,其它屬性按默認值。服務器端程序代碼如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ComCtrls, DB, DBTables, XPMan;
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';
MP_END ='9';
MP_FILEPROPERTY ='0';
iBYTEPERSEND=1024;
type
TForm1 = class(TForm)
Serversocket: TServerSocket;
Query1: TQuery;
GroupBox1: TGroupBox;
Memo1: TMemo;
XPManifest1: TXPManifest;
StatusBar1: TStatusBar;
Button1: TButton;
procedure serversocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure serversocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
procedure serversocketClientError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
fsRecv:TMemoryStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
bReadText:boolean;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Serversocket.Port:=2000;//設置偵聽端口為2000;
bReadText:= true;
Serversocket.Open;
StatusBar1.SimpleText:=' 就緒 ';
end;
procedure TForm1.ServersocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Statusbar1.SimpleText:=' 已和IP地址為 '+Socket.RemoteAddress+' 客戶端連接 ';
end;
procedure TForm1.serversocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
sTemp ,existfile, newfile : string;
bufRecv:Pointer;
iNum:integer;
begin
Memo1.Lines.Add('received size :' + intToStr(Socket.ReceiveLength));
if bReadText then
begin
sTemp:=Socket.ReceiveText;
case sTemp[1] of
MP_QUERY:
begin
Memo1.Lines.Add('receive MP_QUERY');
existfile:=Copy(sTemp,2,Length(STemp)); ;
newfile:= 'c:\Administrator\'+ExtractFileName(existfile);
copyfile(pchar(existfile),pchar(newfile),false);
serversocket.Socket.Connections[0].SendText(MP_ACCEPT);
fsRecv := TMemoryStream.Create;
serversocket.Socket.Connections[0].SendText(MP_REFUSE+'');
end;
MP_FILEPROPERTY:
begin
Memo1.Lines.Add('receive MP_FILEPROPERTY');
serversocket.Socket.Connections[0].SendText(MP_NEXTWILLBEDATA);
end;
MP_NEXTWILLBEDATA:
begin
Memo1.Lines.Add('receive MP_NEXTWILLBEDATA');
bReadText:=false;
serversocket.Socket.Connections[0].SendText(MP_DATA);
end;
MP_END:
begin
Memo1.Lines.Add('receive MP_END');
fsRecv.Free;
bReadText:=true;
end;
MP_ABORT:
begin
Memo1.Lines.Add('receive MP_ABORT');
fsRecv.Free;
bReadText:=true;
end;
MP_CHAT:
begin
Memo1.Lines.Add('receive MP_CHAT');
end;
end;{of case}
end
else
begin
try
GetMem(bufRecv, iBYTEPERSEND);
iNum := Socket.ReceiveBuf(bufRecv^, iBYTEPERSEND);
fsRecv.WriteBuffer(bufRecv^, iNum);
finally
FreeMem(bufRecv);
end;{of try}
bReadText:=true;
if iNum = iBYTEPERSEND THEN
begin
serversocket.Socket.Connections[0].SendText(MP_NEXTWILLBEDATA);
end
else
begin
fsRecv.Free;
serversocket.Socket.Connections[0].SendText(MP_END);
end;
end;
end;
procedure TForm1.serversocketClientError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Memo1.Lines.Add('ErrorCode :' + IntToStr(ErrorCode));
ErrorCode := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
begin
J := serversocket.Socket.ActiveConnections;
Memo1.Lines.Add('ActiveConnectiong is ' + inttostr(j));
end;
end.
客戶端程序編寫:
新建一個工程,并把一個TClientSocket組件放到Form1窗體上,Port設為2000(端口號可任意設置,要求客戶端和服務器端統一),其它屬性按默認值。具體客戶端程序代碼如下:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ComCtrls, XPMan;
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';
MP_END ='9';
MP_FILEPROPERTY ='0';
iBYTEPERSEND=1024;
type
TForm1 = class(TForm)
cs: TClientSocket;
OpenDialog1: TOpenDialog;
StatusBar1: TStatusBar;
GroupBox1: TGroupBox;
edtIPAddress: TEdit;
Edit2: TEdit;
btnSendFile: TButton;
btnConnect: TButton;
XPManifest1: TXPManifest;
GroupBox2: TGroupBox;
Label1: TLabel;
edtSize: TEdit;
Memo1: TMemo;
procedure btnConnectClick(Sender: TObject);
procedure btnSendFileClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
private
fsSend:TFileStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnConnectClick(Sender: TObject);
begin
cs.Address := edtIPAddress.Text;
cs.Port:=2000;
cs.Open;
end;
procedure TForm1.btnSendFileClick(Sender: TObject);
begin
if OpenDialog1.Execute then
Begin
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
edtipaddress.Text:='127.0.0.1';
end;
procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
var
sRecv:string;
iNum:integer;
bufSend:pointer;
begin
sRecv:=Socket.ReceiveText;
Memo1.Lines.Add('sRecv =' + sRecv);
Case sRecv[1] of
MP_REFUSE:ShowMessage('Faint,be refused!');
MP_ACCEPT:begin
Memo1.Lines.Add('MP_ACCEPT');
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
edtSize.Text:=IntToStr(fsSend.Size);
edit2.text:='total count:'+IntToStr(Trunc(fsSend.Size/iBYTEPERSEND)+1);
cs.Socket.SendText(MP_FILEPROPERTY+IntToStr(Trunc(fsSend.Size/iBYTEPERSEND)+1));
fsSend.Seek(0, soFromBeginning);
end;
MP_NEXTWILLBEDATA:begin
Memo1.Lines.Add('MP_NEXTWILLBEDATA');
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_DATA:
begin
Memo1.Lines.Add('MP_DATA');
try
GetMem(bufSend, iBYTEPERSEND);
iNum := fsSend.Read(bufSend^, iBYTEPERSEND);
cs.Socket.SendBuf(bufSend^, iNum);
Memo1.Lines.Add('Send Buf finished');
finally
FreeMem(bufSend);
end;{of try}
end;
MP_END:
begin
Memo1.Lines.Add('MP_END');
fsSend.Free;
end;
MP_ABORT:begin
Memo1.Lines.Add('MP_ABORT');
fsSend.Free;
end;
end;
end;
end.
轉載于:https://www.cnblogs.com/MaxWoods/p/3822416.html
總結
以上是生活随笔為你收集整理的Delphi实例分析:远程传输数据和文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: panel内嵌程序窗体
- 下一篇: 远程控制(3)