您的位置:首页 > 编程语言 > Delphi

Delphi 实现传送文件 <TServerSocket/TClientSocket>

2012-07-06 07:56 495 查看
.建立两个工程Server及Client

分别放TServerSocket及TClientSocket控件,Demo,Edit控件等。

2.设置TServerSocket name为 SS, ServerType为stNonBlocking,TClientSocket name为cs,ClientType为ctNonBlocking表示异步读写信息。注意ClientType和ServerType要相一致.若为ctBlocking则表示同步读写信息。

3.Socket传送文件的顺序图

a)Client-->Server MP_QUERY

b)Server-->Client MP_ACCEPT

c) Client-->Server MP_FileProperty

d)Server-->Client MP_NextWillBeData

e)Client-->Server MP_NextWillBeData

f)Server-->Client MP_DATA

g) Client-->Server 发送数据

h) Server接收数据并处理

i)Client-->Server MP_END结束

4.Client端代码-----------------------------------------------------------------------------------------------------------------

unit UnitClient;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

ScktComp, StdCtrls, Buttons, ExtCtrls, ComCtrls;

Const

//设置协议标志符

//标志将要发送文件名

MP_QUERY ='aaaaa';

//标志服务器拒绝接收

MP_REFUSE ='bbbbb';

//标志服务器同意接收文件

MP_ACCEPT ='ccccc';

//标志将要传递数据

MP_NEXTWILLBEDATA='ddddd';

//标志服务器端准备接收数据

MP_DATA ='eeeee';

//标志客户端取消了本次发送操作

MP_ABORT ='fffff';

//标志已经发送完毕

MP_END='iiiii';

//标志发送的文件长度

MP_FILEPROPERTY='jjjjj';

//指定每次发送包的大小

iBYTEPERSEND=1024;

type

TForm1 = class(TForm)

OpenDialog1: TOpenDialog;

cs: TClientSocket;

Panel1: TPanel;

btnSendFile: TBitBtn;

edtIPAddress: TEdit;

Memo1: TMemo;

edtHostName: TEdit;

RB1: TRadioButton;

RB2: TRadioButton;

ProBar: TProgressBar;

Btncancel: TBitBtn;

Btnexit: TBitBtn;

procedure btnSendFileClick(Sender: TObject);

procedure csRead(Sender: TObject; Socket: TCustomWinSocket);

procedure FormCreate(Sender: TObject);

procedure BtncancelClick(Sender: TObject);

procedure BtnexitClick(Sender: TObject);

private

//定义一个发送文件的数据流

fsSend: TFileStream;

//设置开始状态位

tStart:Boolean;

//标识当前时间

TickCount:Longword;

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

//发送文件

procedure TForm1.btnSendFileClick(Sender: TObject);

begin

//关闭套接字连接

cs.Close;

//初始化进程条

Probar.Position:=0;

if RB1.Checked then

begin

cs.Host:='';

//指定要连接的主机IP地址

cs.Address:=edtIPAddress.Text;

end

else

//指定要连接的主机名

cs.Host:=edtHostName.Text;

//要连接的主机所用端口号

cs.Port:=2000;

//打开套接字连接

cs.Open;

//点击发送确认按钮

if OpenDialog1.Execute then

Begin

//发送连接请求

cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);

end;

end;

//客户端接收来自服务器端的信息

procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);

var

MsgRecv:string;

bufSend:pointer;

iLength:Integer;

begin

//得到客户端发来的信息

MsgRecv:=Socket.ReceiveText;

//取前5位,得到协议标志符

MsgRecv:=copy(MsgRecv,1,5);

//接收到拒绝信息

if MsgRecv=MP_REFUSE then

memo1.Lines.Add('连接请求被拒绝!')

//接收到确认接收信息

else if MsgRecv=MP_ACCEPT then

begin

//为要发送的文件创建文件流

fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);

tStart:=False;

//进度条显示

Probar.Max:=fsSend.Size;

memo1.Lines.Add('开始发送!');

//获取发送开始时的时间

TickCount:=GetTickCount;

//创建文件流并发送文件长度。

Socket.SendText(MP_FILEPROPERTY+inttostr(Trunc(fsSend.Size/iBYTEPERSEND)+1));

end

else if MsgRecv=MP_NEXTWILLBEDATA then

begin

//通知接收端将要传送数据。

Socket.SendText(MP_NEXTWILLBEDATA);

end

else if MsgRecv=MP_DATA then

begin

//接收到确认信息,开始发送数据。

if not tStart then

begin

memo1.Lines.Add('发送数据中... ...');

tStart:=True;

end;

//还有数据没有发送。

if fsSend.Position< fsSend.Size-1 then

begin

iLength:=fsSend.Size-1-fsSend.Position;

//将数据分段发送

if iLength>iBYTEPERSEND then

iLength:=iBYTEPERSEND;

GetMem(bufSend,iLength+1);

try

//读取文件流数据

fsSend.Read(bufSend^,iLength);

//发送长度为iLength的数据

Socket.SendBuf(bufSend^,iLength);

//进度条显示

Probar.Position:=fsSend.Position;

finally

//释放内存

FreeMem(bufSend,iLength+1);

end;

//发送完毕

end else

begin

//通知主机文件传送结束。

Socket.SendText(MP_END);

memo1.Lines.Add('发送完成!');

//获取发送耗时

memo1.Lines.Add('发送耗时'+IntToStr(GetTickCount-TickCount)+'毫秒');

fsSend.Free;

end;

//取消文件发送过程

end else if MsgRecv=MP_ABORT then

begin

memo1.Lines.Add('中止!');

//文件传送取消

fsSend.Free;

end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

Memo1.Clear;

end;

//取消

procedure TForm1.BtncancelClick(Sender: TObject);

begin

//取消文件发送过程

cs.Socket.SendText(MP_ABORT);

end;

procedure TForm1.BtnexitClick(Sender: TObject);

begin

Form1.Close;

end;

end.

5.Server端代码------------------------------------------------------------------------------------------------

unit UnitServer;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, Buttons, ScktComp, ExtCtrls;

Const

//设置协议标志符

//标志将要发送文件名

MP_QUERY ='aaaaa';

//标志服务器拒绝接收

MP_REFUSE ='bbbbb';

//标志服务器同意接收文件

MP_ACCEPT ='ccccc';

//标志将要传递数据

MP_NEXTWILLBEDATA='ddddd';

//标志服务器端准备接收数据

MP_DATA ='eeeee';

//标志客户端取消了本次发送操作

MP_ABORT ='fffff';

//标志已经发送完毕

MP_END='iiiii';

//标志发送的文件长度

MP_FILEPROPERTY='jjjjj';

//指定每次发送包的大小

iBYTEPERSEND=1024;

type

TForm1 = class(TForm)

SaveDialog1: TSaveDialog;

ss: TServerSocket;

Memo1: TMemo;

procedure ssClientRead(Sender: TObject; Socket: TCustomWinSocket);

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

private

//定义一个接收文件的数据流

fsRecv:TFileStream;

//设置开始状态位

tStart:Boolean;

//标识当前时间

TickCount:Longword;

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

//服务器端接收来自客户端的信息

procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);

var

msgr,theFileName:string;

bufRecv:Pointer;

iLength:Integer;

begin

//接收到的数据的长度

iLength:=Socket.ReceiveLength;

//开辟一块新的内存,用来保存接收到的数据

GetMem(bufRecv,iLength);

try

//接收数据

Socket.ReceiveBuf(bufRecv^,iLength);

//将接收到的数据以字符串的形式存到msgr中

msgr:=StrPas(PChar(bufRecv));

//取前5个字符

msgr:=Copy(msgr,1,5);

if msgr=MP_QUERY then

begin

//去掉字符串前后的空格和控制字符

msgr:=Trim(StrPas(PChar(bufRecv)));

//第5个字符后面的字符串为文件名

theFileName:=ExtractFileName(Copy(msgr,6,Length(msgr)));

SaveDialog1.Title:='请选择或输入接收到的数据保存到的文件名:';

SaveDialog1.FileName:=theFileName;

//点击确认保存按钮

if SaveDialog1.Execute then

begin

//为需保存的文件创建文件流

fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);

//如果同意接收数据。

memo1.Lines.Add ('开始接收!');

TickCount:=GetTickCount;

//发送同意接收文件的信息

Socket.SendText(MP_ACCEPT);

tStart:=False;

end

else

//发送拒绝接收文件的信息

Socket.SendText(MP_REFUSE);

end

else if msgr=MP_FILEPROPERTY then

begin

//接收文件长度并说明主机可以接收数据了

Socket.SendText(MP_NEXTWILLBEDATA);

end

else if msgr=MP_NEXTWILLBEDATA then

begin

//要求发送端发送数据

Socket.SendText(MP_DATA);

end else if msgr=MP_END then

begin

memo1.Lines.Add ('文件传送完成!');

memo1.Lines.Add ('接收耗时'+IntToStr(GetTickCount-TickCount)+'毫秒');

fsRecv.Free;

end

//接收到文件传送取消信息

else if msgr=MP_ABORT then

begin

memo1.Lines.Add ('MP_ABORT');

Socket.SendText(MP_ABORT);

fsRecv.Free;

end

else

begin

if not tStart then

begin

memo1.Lines.Add('接收数据...');

tStart:=True;

end;

//将接收缓冲区数据写入文件

fsRecv.WriteBuffer(bufRecv^,iLength);

//通知客户端继续发送数据

Socket.SendText(MP_DATA);

end;

finally

//释放内存

FreeMem(bufRecv,iLength);

end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

Memo1.Clear;

//设置的监听端口

ss.Port:=2000;

//开始监听

ss.Open;

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

ss.Close;

end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐