您的位置:首页 > 理论基础 > 计算机网络

用TTcpClient和TTcpServer进行文件的传输

2016-08-23 10:31 288 查看
发送数据时有Sendln,SendBuf,SendStream。接收数据时有Receiveln,ReceiveBuf,当时我很奇怪为什么没有ReceiveStream。因为很自然的想到是对应关系的。但当时我不知道,发数据时是一小段一小段地发的

看看SendStream代码:

[delphi] view
plain copy

function TBaseSocket.SendStream(AStream: TStream): Integer;  

var  

  BufLen: Integer;  

  Buffer: array[0..511] of Byte;  

begin  

  Result := 0;  

  if Assigned(AStream) then  

  begin  

    repeat  

      BufLen := AStream.Read(Buffer, SizeOf(Buffer));  

    until (BufLen = 0) or (SendBuf(Buffer, BufLen) = SOCKET_ERROR);  

  end;  

end;  

从以上代码可看到,SendStream一次最多发送512字节的内容,所以,我们这接收端循环用ReceiveBuf接收就可以了。不用像以前那样写得又复杂乱。

发送端(Client)代码:

[delphi] view
plain copy

unit Unit1;  

  

interface  

  

uses  

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

  Dialogs, StdCtrls, Sockets;  

  

type  

  TForm1 = class(TForm)  

    tcpclnt1: TTcpClient;  

    btn1: TButton;  

    procedure btn1Click(Sender: TObject);  

  private  

    { Private declarations }  

  public  

    { Public declarations }  

  end;  

  

var  

  Form1: TForm1;  

  

implementation  

  

{$R *.dfm}  

  

procedure TForm1.btn1Click(Sender: TObject);  

var  

  f : TFileStream;//文件流  

  i : Integer;  

  fn : string;//文件名  

begin  

  {用for循环是实现发送多个文件,如果只是发送一个文件,不用循环}  

  for i := 1 to 11 do  

  begin  

    tcpclnt1.Connect; //连接服务端,我把TTcpClient的BlockMode设为bmBlocking  

    fn := 'a' + IntToStr(i) + '.rar';  

    f := TFileStream.Create('d:/send/' + fn,fmOpenRead); //用文件流以读方式打开要发送的文件  

    tcpclnt1.Sendln(fn); //给对方发送文件名  

    tcpclnt1.Sendln(IntToStr(f.Size)); //给对方发送文件大小  

    tcpclnt1.SendStream(f); //发送文件流  

    f.Free;//释放文件流  

    tcpclnt1.Disconnect;//关闭连接  

  end;  

end;  

  

end.  

 

接收端(Server)代码:

[delphi] view
plain copy

unit Unit1;  

  

interface  

  

uses  

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

  Dialogs, Sockets;  

  

type  

  TForm1 = class(TForm)  

    tcpsrvr1: TTcpServer;  

    procedure FormActivate(Sender: TObject);  

    procedure tcpsrvr1Accept(Sender: TObject;  

      ClientSocket: TCustomIpClient);  

  private  

    { Private declarations }  

  public  

    { Public declarations }  

  end;  

  

var  

  Form1: TForm1;  

  

implementation  

  

{$R *.dfm}  

  

procedure TForm1.FormActivate(Sender: TObject);  

begin  

  tcpsrvr1.Open; //在OnActive事件中启动TCPServer的监听  

end;  

  

procedure TForm1.tcpsrvr1Accept(Sender: TObject;  

  ClientSocket: TCustomIpClient);  

var  

  f : TFileStream;  //文件流  

  iFileSize : Integer; //文件大小  

  iTotalRec : Integer; //总接收到的字节数,用来和文件大小比较,如果比文件大小的值要小,就还要继续接收  

  iacRec    : Integer; //每一次ReceiveBuf实际接收到的字节数  

  pbuf      : Pointer; //缓存指针  

  i : Integer;  

  fn : string; //文件名  

begin  

    GetMem(pbuf,512); //我们一次最多也读取512字节  

    try  

      iTotalRec := 0;   //先把总接收到的字节数置零  

      fn := ClientSocket.Receiveln; //接收文件名  

      iFileSize := StrToInt(ClientSocket.Receiveln); //接收文件大小,接收到的字符串,要转成integer  

      f := TFileStream.Create('d:/rec/'+ fn,fmCreate);//创建文件  

      try  

        {如果接收到的总字节数小于文件总字节数且实际接收字节数不为-1就一直循环接收}  

        while iTotalRec < iFileSize  do  

        begin  

          iacRec := ClientSocket.ReceiveBuf(pbuf^,512);//一次接收512字节  

          if iacRec = -1 then  

            Break;//如果实际接收字节数是-1表示出错了,退出循环(应该写个log,或作出错处理什么的)  

          f.Write(pbuf^,iacRec);//把接收到的数据写到文件流中  

          Inc(iTotalRec,iacRec);//叠加接收到的总字节数  

        end;  

      finally  

        f.Free; //释放流  

      end;  

    finally  

      FreeMem(pbuf);//释放内存  

    end;  

end;  

  

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