[转载]Delphi ServerSocket,ClientSocket示例_batman_新浪博客

[转载]Delphi ServerSocket,ClientSocket示例_batman_新浪博客,batman,

来源: [转载]Delphi ServerSocket,ClientSocket示例_batman_新浪博客

Delphi TServerSocket,TClientSocket实现传送文件代码

1.建立两个工程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.

分享到: 更多 (0)