用TTcpClient和TTcpServer进行文件的传输
Posted 朝闻道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用TTcpClient和TTcpServer进行文件的传输相关的知识,希望对你有一定的参考价值。
发送数据时有Sendln,SendBuf,SendStream。接收数据时有Receiveln,ReceiveBuf,当时我很奇怪为什么没有ReceiveStream。因为很自然的想到是对应关系的。但当时我不知道,发数据时是一小段一小段地发的
看看SendStream代码:
- 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)代码:
- 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)代码:
- 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.
以上是关于用TTcpClient和TTcpServer进行文件的传输的主要内容,如果未能解决你的问题,请参考以下文章
最简单的TTcpServer与TTcpClient通信实例-Delphi