1,593
社区成员
发帖
与我相关
我的任务
分享
unit client_new;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, IdBaseComponent,IdGlobal,
IdComponent, IdTCPConnection, IdTCPClient, Vcl.ComCtrls, IdAntiFreezeBase,
IdAntiFreeze;
type
TMyRecord = record
Details:string[255];
FileName:string[255];
FileSize:integer;
FileDate:TDateTime;
RecordSize:Integer;
end;
type
TForm1 = class(TForm)
chkConnect: TCheckBox;
edHost: TEdit;
IdTCPClient1: TIdTCPClient;
Memo1: TMemo;
edSendFile: TEdit;
btnGetFile: TButton;
btnSendFile: TButton;
OpenDialog1: TOpenDialog;
ProgressBar1: TProgressBar;
IdAntiFreeze1: TIdAntiFreeze;
procedure chkConnectClick(Sender: TObject);
procedure btnGetFileClick(Sender: TObject);
procedure btnSendFileClick(Sender: TObject);
procedure IdTCPClient1Connected(Sender: TObject);
procedure IdTCPClient1Disconnected(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SetClientState(sState:Boolean);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnGetFileClick(Sender: TObject);
begin
OpenDialog1.Execute();
edSendFile.Text := OpenDialog1.FileName ;
end;
procedure TForm1.btnSendFileClick(Sender: TObject);
var
AFileHandler : integer;
AMyRecord : TMyRecord;
Abuf:TidBytes;
AStream:TFileStream;
ASize:int64;
cmt:int64;
Bbuf:array [0..4096] of byte;
begin
//先验证文件是否存在
if FileExists(edSendFile.Text) = false then
begin
showmessage('No File');
exit;
end;
//获得文件信息
AFileHandler:=FileOpen(edSendFile.Text,fmOpenRead);
//存储信息在record中
AMyRecord.FileName := extractfilename(edSendFile.Text);
AMyRecord.FileDate := now;
AMyRecord.FileSize := FileSeek(AFileHandler,0,2);
AMyRecord.Details := 'file test';
AMyRecord.RecordSize := sizeof(AMyRecord);
FileSeek(AFileHandler,0,0);
// FileClose(AFileHandler);
//传输record,需要转换为buf发送
Abuf := RawToBytes(AMyRecord,sizeof(AMyRecord));
IdTCPClient1.IOHandler.Write(int64(length(Abuf)));
IdTCPClient1.IOHandler.WriteBufferOpen ;
IdTCPClient1.IOHandler.Write(Abuf,length(Abuf));
// IdTCPClient1.IOHandler.WriteBufferFlush;
// IdTCPCLient1.IOHandler.WriteBufferClose;
//获得反馈信息,默认服务器直接接收文件,先获得流,再做事儿
// AStream:=TFileStream.Create;
//get stream from file
// AStream.LoadFromFile(edSendFile.Text); //这是一个败笔,不应该这样做,更何况也无法一次性读取文件
//正确的办法是按照一定大小读文件到流,然后传输流,问题成为如何分段读入文件到流。
// AStream.Position := 0;
//获得流大小,并将其拆分为4096小块发送
// ASize := AStream.Size ;
ASize := AMyRecord.FileSize;
IdTCPClient1.IOHandler.Write(ASize);
// IdTCPClient1.IOHandler.Write(AStream,ASize,false ); //good job
ProgressBar1.Max := ASize;
ProgressBar1.Position := 0;
Memo1.Lines.Add('File Sent@'+TimeToStr(now));
Application.ProcessMessages;//啥作用呢?
// IdTCPClient1.IOHandler.WriteBufferOpen;
//需弄清楚此处的限制条件是针对什么,应该针对传出的内容而定。
while true do
begin
cmt := FileRead(AFileHandler,Bbuf,4096);//read 4096 byte from file;
IdTCPClient1.IOHandler.Write(cmt);
Abuf := RawToBytes(Bbuf,cmt);
IdTCPClient1.IOHandler.Write(Abuf,length(Abuf));//there is no difference between Abuf and Bbuf except type
//这样仍然解决不了大文件传输的问题,报错原因是内存过大。
//将流写入buf
// cmt := AStream.Read(Bbuf,4096);//读入流中,然后传递
// IdTCPClient1.IOHandler.Write(cmt);
// Abuf:=rawToBytes(Bbuf,cmt);
// IdTCPClient1.IOHandler.Write(Abuf,length(Abuf));
ProgressBar1.Position := ProgressBar1.Position + cmt;
if cmt<4096 then
break;
end;
// AStream.Write(Bbuf,ASize);
// cmt:= sizeof(Bbuf);
// IdTCPClient1.IOHandler.Write(cmt);
// Abuf:=rawToBytes(Bbuf,cmt);
// IdTCPClient1.IOHandler.Write(Abuf,length(Abuf));
// ProgressBar1.Position := ProgressBar1.Position + ASize;
IdTCPClient1.IOHandler.WriteBufferFlush;
IdTCPClient1.IOHandler.WriteBufferClose;
// AStream.Free;
FileClose(AFileHandler);
Memo1.Lines.Add('Server receive file @'+IdTCPClient1.IOHandler.ReadLn());
ProgressBar1.Position :=0;
end;
procedure TForm1.chkConnectClick(Sender: TObject);
begin
if chkConnect.Checked = true then
SetClientState(true)
else
SetClientState(false);
end;
procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
Memo1.Lines.Add('Client Connect');
end;
procedure TForm1.IdTCPClient1Disconnected(Sender: TObject);
begin
Memo1.Lines.Add('Client Disconnect');
end;
procedure TForm1.SetClientState(sState: Boolean);
begin
if sState = true then
begin
IdTCPClient1.Host := edHost.Text;
IdTCPClient1.Port := 8800;
IdTCPClient1.Connect;
end
else
IdTCPClient1.Disconnect ;
chkConnect.Checked := sState;
end;
end.
unit server_new;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, IdBaseComponent, IdComponent,IdGlobal,
IdCustomTCPServer, IdTCPServer, Vcl.StdCtrls, Vcl.ComCtrls;
type
TMyRecord = record
Details:string[255];
FileName:string[255];
FileSize:integer;
FileDate:TDateTime;
RecordSize:Integer;
end;
type
TForm1 = class(TForm)
chkStart: TCheckBox;
Memo1: TMemo;
IdTCPServer1: TIdTCPServer;
ProgressBar1: TProgressBar;
procedure IdTCPServer1Connect(AContext: TIdContext);
procedure chkStartClick(Sender: TObject);
procedure IdTCPServer1Disconnect(AContext: TIdContext);
procedure IdTCPServer1Exception(AContext: TIdContext;
AException: Exception);
procedure IdTCPServer1Execute(AContext: TIdContext);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.chkStartClick(Sender: TObject);
begin
IdTCPServer1.DefaultPort := 8800;
idTCPServer1.Active := chkStart.Checked;
end;
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
Memo1.Lines.Add('Client connect');
end;
procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
Memo1.Lines.Add('Client Disconnect');
end;
procedure TForm1.IdTCPServer1Exception(AContext: TIdContext;
AException: Exception);
begin
Memo1.Lines.Add('Exception '+ AException.Message );
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
AMyRecord:TMyRecord;
ASize:int64;
cmt:int64;
Abuf:TIdBytes;
Bbuf:array[0..4096] of byte;
AStream:TFileStream;
begin
//获得信息,并进行转换
// ASize := AContext.Connection.IOHandler.ReadInt64();
with AContext.Connection.IOHandler do
begin
ASize := ReadInt64();
ReadBytes(Abuf,ASize,false);
BytesToRaw(Abuf,AMyRecord,sizeof(AMyRecord));
//将收到的信息写出来
Memo1.Lines.Add('Receive record:');
Memo1.Lines.Add('FileName = ' + AMyRecord.FileName);
Memo1.Lines.Add('FileSize = ' + IntToStr(AMyRecord.FileSize));
Memo1.Lines.Add('Date = ' + DateToStr(AMyRecord.FileDate));
Memo1.Lines.Add('Time = ' + TimeToStr(AMyRecord.FileDate));
Memo1.Lines.Add('RecordSize = ' + IntToStr(AMyRecord.Recordsize));
//继续传输文件到流中
if AMyRecord.Details <> 'file test' then
begin
Memo1.Lines.Add('Record Receive successfully');
exit;
end;
AStream:=TFileStream.Create(AMyRecord.FileName,fmCreate); //此处没有该文件,能否这样作呢
ASize := ReadInt64();
// ReadStream(AStream,ASize,false);
ProgressBar1.Position := 0;
ProgressBar1.Max := ASize;
while ASize>4096 do //the biggest problem is the stream cannot be too big
begin
cmt := ReadInt64();
ReadBytes(Abuf,cmt);
BytesToraw(Abuf,Bbuf,sizeof(Bbuf));
// AStream.Write(Bbuf,4096);
AStream.Write(Bbuf,4096); //写入内存,实际上还是应该直接写入文件才行
ProgressBar1.Position := ProgressBar1.Position + cmt;
inc(ASize,-4096);
end;
cmt := ReadInt64();
ReadBytes(Abuf,cmt);
BytesToraw(Abuf,Bbuf,sizeof(Bbuf));
AStream.Write(Bbuf,cmt);
ProgressBar1.Position := ProgressBar1.Position + cmt;
// AStream.SaveToFile(AMyRecord.FileName);
AStream.Free;
Memo1.Lines.Add('File saved @'+TimeToStr(now));
writeln(TimeToStr(now));
showmessage('file receiving over');
ProgressBar1.Position:=0;
end;
end;
end.