zoukankan      html  css  js  c++  java
  • 用TTcpClient和TTcpServer进行文件的传输

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

    看看SendStream代码:

    [delphi] view plain copy
     
     
    1. function TBaseSocket.SendStream(AStream: TStream): Integer;  
    2. var  
    3.   BufLen: Integer;  
    4.   Buffer: array[0..511] of Byte;  
    5. begin  
    6.   Result := 0;  
    7.   if Assigned(AStream) then  
    8.   begin  
    9.     repeat  
    10.       BufLen := AStream.Read(Buffer, SizeOf(Buffer));  
    11.     until (BufLen = 0) or (SendBuf(Buffer, BufLen) = SOCKET_ERROR);  
    12.   end;  
    13. end;  

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

    发送端(Client)代码:

    [delphi] view plain copy
     
     
    1. unit Unit1;  
    2.   
    3. interface  
    4.   
    5. uses  
    6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
    7.   Dialogs, StdCtrls, Sockets;  
    8.   
    9. type  
    10.   TForm1 = class(TForm)  
    11.     tcpclnt1: TTcpClient;  
    12.     btn1: TButton;  
    13.     procedure btn1Click(Sender: TObject);  
    14.   private  
    15.     { Private declarations }  
    16.   public  
    17.     { Public declarations }  
    18.   end;  
    19.   
    20. var  
    21.   Form1: TForm1;  
    22.   
    23. implementation  
    24.   
    25. {$R *.dfm}  
    26.   
    27. procedure TForm1.btn1Click(Sender: TObject);  
    28. var  
    29.   f : TFileStream;//文件流  
    30.   i : Integer;  
    31.   fn : string;//文件名  
    32. begin  
    33.   {用for循环是实现发送多个文件,如果只是发送一个文件,不用循环}  
    34.   for i := to 11 do  
    35.   begin  
    36.     tcpclnt1.Connect; //连接服务端,我把TTcpClient的BlockMode设为bmBlocking  
    37.     fn := 'a' + IntToStr(i) + '.rar';  
    38.     f := TFileStream.Create('d:/send/' + fn,fmOpenRead); //用文件流以读方式打开要发送的文件  
    39.     tcpclnt1.Sendln(fn); //给对方发送文件名  
    40.     tcpclnt1.Sendln(IntToStr(f.Size)); //给对方发送文件大小  
    41.     tcpclnt1.SendStream(f); //发送文件流  
    42.     f.Free;//释放文件流  
    43.     tcpclnt1.Disconnect;//关闭连接  
    44.   end;  
    45. end;  
    46.   
    47. end.  

    接收端(Server)代码:

    [delphi] view plain copy
     
     
    1. unit Unit1;  
    2.   
    3. interface  
    4.   
    5. uses  
    6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
    7.   Dialogs, Sockets;  
    8.   
    9. type  
    10.   TForm1 = class(TForm)  
    11.     tcpsrvr1: TTcpServer;  
    12.     procedure FormActivate(Sender: TObject);  
    13.     procedure tcpsrvr1Accept(Sender: TObject;  
    14.       ClientSocket: TCustomIpClient);  
    15.   private  
    16.     { Private declarations }  
    17.   public  
    18.     { Public declarations }  
    19.   end;  
    20.   
    21. var  
    22.   Form1: TForm1;  
    23.   
    24. implementation  
    25.   
    26. {$R *.dfm}  
    27.   
    28. procedure TForm1.FormActivate(Sender: TObject);  
    29. begin  
    30.   tcpsrvr1.Open; //在OnActive事件中启动TCPServer的监听  
    31. end;  
    32.   
    33. procedure TForm1.tcpsrvr1Accept(Sender: TObject;  
    34.   ClientSocket: TCustomIpClient);  
    35. var  
    36.   f : TFileStream;  //文件流  
    37.   iFileSize : Integer; //文件大小  
    38.   iTotalRec : Integer; //总接收到的字节数,用来和文件大小比较,如果比文件大小的值要小,就还要继续接收  
    39.   iacRec    : Integer; //每一次ReceiveBuf实际接收到的字节数  
    40.   pbuf      : Pointer; //缓存指针  
    41.   i : Integer;  
    42.   fn : string; //文件名  
    43. begin  
    44.     GetMem(pbuf,512); //我们一次最多也读取512字节  
    45.     try  
    46.       iTotalRec := 0;   //先把总接收到的字节数置零  
    47.       fn := ClientSocket.Receiveln; //接收文件名  
    48.       iFileSize := StrToInt(ClientSocket.Receiveln); //接收文件大小,接收到的字符串,要转成integer  
    49.       f := TFileStream.Create('d:/rec/'+ fn,fmCreate);//创建文件  
    50.       try  
    51.         {如果接收到的总字节数小于文件总字节数且实际接收字节数不为-1就一直循环接收}  
    52.         while iTotalRec < iFileSize  do  
    53.         begin  
    54.           iacRec := ClientSocket.ReceiveBuf(pbuf^,512);//一次接收512字节  
    55.           if iacRec = -then  
    56.             Break;//如果实际接收字节数是-1表示出错了,退出循环(应该写个log,或作出错处理什么的)  
    57.           f.Write(pbuf^,iacRec);//把接收到的数据写到文件流中  
    58.           Inc(iTotalRec,iacRec);//叠加接收到的总字节数  
    59.         end;  
    60.       finally  
    61.         f.Free; //释放流  
    62.       end;  
    63.     finally  
    64.       FreeMem(pbuf);//释放内存  
    65.     end;  
    66. end;  
    67.   
    68. end.  
    http://blog.csdn.net/zang141588761/article/details/52288692
  • 相关阅读:
    ip netns
    PPT动手动脑1
    暑假作业日总结
    暑假作业日总结
    课前测试总结
    暑假作业日总结
    大二上每日总结
    暑假作业日总结
    大二上每日总结
    暑假作业日总结
  • 原文地址:https://www.cnblogs.com/findumars/p/6711191.html
Copyright © 2011-2022 走看看