zoukankan      html  css  js  c++  java
  • Delphi7开发简单文件传输

    1.安装 Tclientsocket, Tserversocket控件

    菜单component->Install Packets

      

    按Add按钮,选择delphi目录里的bin目录下的Delphi7是dclsockets70.bpl(delphi2010是

    dclsockets140.bpl),然后TClientSocket和TServerSocket控件就会出现在Internet页上了


    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结束


    Server端代码

    unit SvrU;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ScktComp, 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)
        Memo1: TMemo;
        Memo2: TMemo;
        ss: TServerSocket;
        StatusBar1: TStatusBar;
        Button2: TButton;
        SaveDialog1: TSaveDialog;
        procedure FormShow(Sender: TObject);
        procedure ssClientConnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ssClientDisconnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure Memo2KeyPress(Sender: TObject; var Key: Char);
        procedure ssClientRead(Sender: TObject;      Socket: TCustomWinSocket);
        procedure Button2Click(Sender: TObject);
        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}
    
    var
      ClientSock: TCustomWinSocket;
    
    procedure TForm1.FormShow(Sender: TObject);
    begin
      ss.Active := True;
    end;
    
    procedure TForm1.ssClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      ClientSock := Socket;
      Memo2.Enabled := True;
      Memo2.SetFocus();
      StatusBar1.SimpleText := 'Connected!';
    end;
    
    procedure TForm1.ssClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      ClientSock := nil;
      Memo2.Enabled := False;
      StatusBar1.SimpleText := 'Disconnected!';
    end;
    
    procedure TForm1.Memo2KeyPress(Sender: TObject; var Key: Char);
    begin
      if Key = #13 then
      begin
        Button2Click(Sender);
        Key := #0;
      end;
    end;
    
    //接收文本
    //procedure TForm1.ssClientRead(Sender: TObject;
    //  Socket: TCustomWinSocket);
    //begin
    //  Memo1.Lines.Add('Remote:');
    //  Memo1.Lines.Add(Socket.ReceiveText());
    //  Memo1.Lines.Add('');
    //end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      if Memo2.Text <> '' then
      begin
        ClientSock.SendText(Memo2.Text);
        Memo1.Lines.Add('Local:');
        Memo1.Lines.Add(Memo2.Text);
        Memo1.Lines.Add('');
        Memo2.Clear();
      end;
    end;
    
    
    //服务器端接收来自客户端的信息
    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:=8321;
    //开始监听
    ss.Open;
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    ss.Close;
    end;
    
    end.
    View Code

    主要设置,端口,要与客户端一 致 

    Client端代码

    unit CltU;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ScktComp, 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)
        Memo1: TMemo;
        Memo2: TMemo;
        ClientSocket1: TClientSocket;
        Edit1: TEdit;
        Label1: TLabel;
        Button1: TButton;
        StatusBar1: TStatusBar;
        Button2: TButton;
        Button3: TButton;
        Probar: TProgressBar;
        RB1: TRadioButton;
        OpenDialog1: TOpenDialog;
        procedure ClientSocket1Connect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ClientSocket1Disconnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure Button1Click(Sender: TObject);
        procedure Memo2KeyPress(Sender: TObject; var Key: Char);
    //    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
    
        procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
      private
            //定义一个发送文件的数据流
        fsSend: TFileStream;
        //设置开始状态位
        tStart:Boolean;
        //标识当前时间
        TickCount:Longword;
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    
    procedure TForm1.ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      Memo2.Enabled := True;
      Memo2.SetFocus();
      StatusBar1.SimpleText := 'Connected!';
    end;
    
    procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      Memo2.Enabled := False;
      StatusBar1.SimpleText := 'Disconnected!';
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ClientSocket1.Host := Edit1.Text;
      ClientSocket1.Open();
    end;
    
    procedure TForm1.Memo2KeyPress(Sender: TObject; var Key: Char);
    begin
      if Key = #13 then
      begin
        Button2Click(Sender);
        Key := #0;
      end;
    end;
    //发送文本
    //procedure TForm1.ClientSocket1Read(Sender: TObject;
    //  Socket: TCustomWinSocket);
    //begin
    //  Memo1.Lines.Add('Remote:');
    //  Memo1.Lines.Add(Socket.ReceiveText());
    //  Memo1.Lines.Add('');
    //end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      if Memo2.Text <> '' then
      begin
        ClientSocket1.Socket.SendText(Memo2.Text);
        Memo1.Lines.Add('Local:');
        Memo1.Lines.Add(Memo2.Text);
        Memo1.Lines.Add('');
        Memo2.Clear();
      end;
    end;
    
    //发送文件
    procedure TForm1.Button3Click(Sender: TObject);
    begin
    //关闭套接字连接
    ClientSocket1.Close;
    //初始化进程条
    Probar.Position:=0;
    if RB1.Checked then
    begin
       ClientSocket1.Host:='';
       //指定要连接的主机IP地址
       ClientSocket1.Address:=Edit1.Text;
    end
    else
    //指定要连接的主机名
    ClientSocket1.Host:=Edit1.Text;
    //要连接的主机所用端口号
    ClientSocket1.Port:=8321;
    //打开套接字连接
    ClientSocket1.Open;
    //点击发送确认按钮
    if OpenDialog1.Execute then
    Begin
    //发送连接请求
        ClientSocket1.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;
    
    end.
    View Code

    主要设置,服务器IP,端口,要与服务端一 致

     


     示例源代码下载

  • 相关阅读:
    从一个简单的例子谈谈package与import机制
    java 中public 类
    java 内部类
    使用Maven运行Java main的3种方式
    递归删除目录下.svn文件
    react-redux的connect()方法
    react 调用 function 的写法 及 解决 react onClick 方法自动执行
    react 路由传参
    react-redux 和 redux-saga 小结
    百度地图 放大或缩小后 中心点偏移(中心点不是在放大前的点)
  • 原文地址:https://www.cnblogs.com/tulater/p/13867420.html
Copyright © 2011-2022 走看看