用TTcpClient和TTcpServer进行文件的传输
2017-04-14 22:13
483 查看
发送数据时有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.
http://blog.csdn.net/zang141588761/article/details/52288692
看看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.
http://blog.csdn.net/zang141588761/article/details/52288692
相关文章推荐
- 用TTcpClient和TTcpServer进行文件的传输
- 再说“用TTcpClient和TTcpServer进行文件的传输”
- 用TTcpClient和TTcpServer进行文件的传输
- 用TTcpClient和TTcpServer进行文件的传输
- delphi用IdTCPServer和IdTCPClient传输文件
- SpringCloud(第 032 篇)配置服务端ClientServer对配置文件内容进行RSA加解密
- SpringCloud(第 030 篇)配置服务端ClientServer对配置文件内容进行对称加解密
- SpringCloud(第 032 篇)配置服务端ClientServer对配置文件内容进行RSA加解密
- 用IdTCPServer和IdTCPClient传输文件
- (死亡历险)Delphi7 IdTCPClient1,IdTCPServer1客户端向服务端发送指令进行文件下载
- SpringCloud(第 032 篇)配置服务端ClientServer对配置文件内容进行RSA加解密
- SpringCloud(第 030 篇)配置服务端ClientServer对配置文件内容进行对称加解密
- 用IdTCPServer和IdTCPClient传输文件
- SpringCloud(第 030 篇)配置服务端ClientServer对配置文件内容进行对称加解密
- socket client传文件到server,server端接收成功后给客户端反馈一个信息
- 在Ubuntu系统中文件进行加密传输
- Android使用Socket(Tcp/Udp)协议进行数据传输(传输大文件)
- 网络代理服务Agent,服务端.client 连接server 进行通信
- Client:TSocketConnection和Server:Scktsrvr关系----压缩数据传输
- 使用Apache 的 FTP Client获取FTP服务器上的文件列表FTP response 421 received.Server closed connection问题的解决