博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delphi TServerSocket,TClientSocket实现传送文件代码
阅读量:6412 次
发布时间:2019-06-23

本文共 7089 字,大约阅读时间需要 23 分钟。

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;interfaceusesWindows, 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;typeTForm1 = 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;varForm1: TForm1;implementation{$R *.DFM}//发送文件procedure TForm1.btnSendFileClick(Sender: TObject);begin//关闭套接字连接cs.Close;//初始化进程条Probar.Position:=0;if RB1.Checked thenbegin   cs.Host:='';   //指定要连接的主机IP地址   cs.Address:=edtIPAddress.Text;endelse//指定要连接的主机名cs.Host:=edtHostName.Text;//要连接的主机所用端口号cs.Port:=2000;//打开套接字连接cs.Open;//点击发送确认按钮if OpenDialog1.Execute thenBegin//发送连接请求    cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);end;end;//客户端接收来自服务器端的信息procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);varMsgRecv: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 thenbegin    //为要发送的文件创建文件流    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));endelse if MsgRecv=MP_NEXTWILLBEDATA thenbegin    //通知接收端将要传送数据。    Socket.SendText(MP_NEXTWILLBEDATA);endelse if MsgRecv=MP_DATA thenbegin    //接收到确认信息,开始发送数据。    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 thenbegin    memo1.Lines.Add('中止!');    //文件传送取消    fsSend.Free;end;end;procedure TForm1.FormCreate(Sender: TObject);beginMemo1.Clear;end;//取消procedure TForm1.BtncancelClick(Sender: TObject);begin//取消文件发送过程cs.Socket.SendText(MP_ABORT);end;procedure TForm1.BtnexitClick(Sender: TObject);beginForm1.Close;end;end.

5.Server端代码

unit UnitServer;interfaceusesWindows, 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;typeTForm1 = 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;varForm1: TForm1;implementation{$R *.DFM}//服务器端接收来自客户端的信息procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);varmsgr,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);beginMemo1.Clear;//设置的监听端口ss.Port:=2000;//开始监听ss.Open;end;procedure TForm1.FormDestroy(Sender: TObject);beginss.Close;end;end.

 

转载地址:http://bsdra.baihongyu.com/

你可能感兴趣的文章
java线程同步原理(lock,synchronized)
查看>>
MyEclipse中使用Hql编辑器找不到Hibernate.cfg.xml文件解决方法
查看>>
yRadio以及其它
查看>>
第四节 对象和类
查看>>
闪迪(SanDisk)U盘防伪查询(官方网站)
查看>>
Android onMeasure方法介绍
查看>>
微信公众号搭建营销型房产项目程序后台开发
查看>>
无锁数据结构
查看>>
MySQL的变量查看和设置
查看>>
android onNewIntent
查看>>
XML特殊符号
查看>>
kaptcha可配置项
查看>>
JavaMail邮箱验证用户注册
查看>>
系统时间——ntpd
查看>>
反射实现AOP动态代理模式(Spring AOP实现原理)
查看>>
Spring MVC 4.x + fastjson 1.2.7,封装的List<?>参数
查看>>
js选中问题
查看>>
protobuf
查看>>
4.Java基础复习--Set
查看>>
七:Mysql的乐观锁与悲观锁机制
查看>>