最近用TServerSocket/TClientSocket做了一个简单的文件传输的东东,发现速度很慢,而且传大一点的文件就会像死机一样(用流的方式实现)。后来换成了TIdTCPServer/TIdTCPClient,用映射内存共享的方式实现了,速度也不慢,但文件的大小超出了内存的大小(物理内存+虚拟内存)就会报地址错误。这两种方式都有一个致命的问题一直都没有解决:当一个客户端和服务器正在传文件,如果有另一个客户端又连上服务器,则服务器会断掉与第一个客户端的连线。有没有哪位兄弟做过类似的东东,即:一个服务器可以同时向多个客户端传送文件。由于我是初级用户,一次只能最多给100分,如果不够,可以另起一个贴再给分。(软件的要求是:服务器24H挂在一台机器上,当有客户端连线上服务器,服务器作出回答,客户端3秒内收到回答后请求传送文件,开始从服务器传文件到客户端)
unit uUpdate;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient;const
packsize=65000;//°ü´óСtype
TRevBuffer=packed record
masmID:Word;//δÓÃ
ID:Word;//񈬀
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;
MD:Int64;
end;
TSendBuffer=packed record
masmID:Word;//δÓÃ
ID:Word;//񈬀
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;//Êý¾ÝÇøµÄ´óС
MD:Int64;//ÕªÒª
buffer:Array[0..packsize-1] of byte;
end;//ÐÔÄܼà²âÏß³Ì
type
TMonitorThread = class(TThread)
private
SecondTimer:DWord;
protected
procedure Execute; override;
public
constructor Create; reintroduce;
end;type
TForm1 = class;
TSocketThread = class(TThread)
private
Rev:TRevBuffer;
Snd:TSendBuffer;
PRev,PSnd,TP,UP:PByte;
TempPointer:PByte;
RemainBytes:Word;
ReceivedCounter:Integer;
HeaderFinished,BodyFinished,PushTransporting:Boolean; ThreadForm : TForm1;
FClient:TIdTCPClient;
SendBytes:DWord;//¸ÃÏß³ÌÒª´«ÊäµÄ×Ö½ÚÊý FileMapPointer:PByte;//ÄÚ´æÓ³ÏñÎļþÖ¸Õë
// SendBlock:DWord;//¸ÃÏß³ÌÒª´«ÊäµÄ¿éÊý
TransforCount,Transfor_T:DWord;
procedure Process;
procedure Branch;
procedure RequestTransfer;
procedure ServerReady;
procedure Transporting;
protected
procedure Execute; override;
public
constructor Create(F: TForm1;Count:DWord;FileMap:PByte); reintroduce;
end;
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Label1: TLabel;
Label3: TLabel;
Edit1: TEdit;
Edit2: TEdit;
btnChoice: TButton;
Button1: TButton;
procedure btnChoiceClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
FileSize:DWord;//Òª´«ÊäµÄÎļþ´óС
Instructor:TProgressBar;
MP:PByte;
SocketThread:TSocketThread;
Event:THandle;
MonitorThread:TMonitorThread;
{ Public declarations }
end;var
Form1: TForm1; var
SentBytes:LongWord;
implementation{$R *.dfm}constructor TSocketThread.Create(F: TForm1;Count:DWord;FileMap:PByte);
begin
inherited Create(false);
ThreadForm := F;
SendBytes:=Count;
FileMapPointer:=FileMap;
SentBytes:=0;
ReceivedCounter:=32;
PRev:=@Rev;
PSnd:=@Snd;
TempPointer:=PRev;
end;procedure TForm1.btnChoiceClick(Sender: TObject);
var
F:Tsearchrec;
begin
IF OpenDialog1.Execute then
Edit2.Text:=OpenDialog1.FileName;
IF FindFirst(Edit2.Text,FaAnyfile,F)=0 then
FileSize:=F.Size;
end;procedure TForm1.Button1Click(Sender: TObject);
var
H,I,J,K,U:Integer;
FH,MH:THandle;
begin
//½¨Á¢ÎļþÄÚ´æÓ³Ïñ
// Button1.Enabled:=False;
FH:=FileOpen(Edit2.Text,fmOpenRead);
MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil);
CloseHandle(FH);
MP:=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);
CloseHandle(MH);
If Instructor<>nil then
Instructor.Free;
Instructor:=TProgressBar.Create(self);
Instructor.Left:=0;
Instructor.Top:=Edit2.Top+Edit2.Height+15;
Instructor.Width:=424;
Instructor.Step:=1;
Instructor.Parent:=Form1; SocketThread:=TSocketThread.Create(self,FileSize,MP);
Event:=CreateEvent(nil,False,False,nil);
end;
var
H,I,J:Integer;
Thread_L:Integer;
CurPointerOffset:DWord;
FileName:String[255];
begin
FClient:=TIdTCPClient.Create(nil);
FClient.Host:=ThreadForm.Edit1.Text;
FClient.Port:=10888;
try
FClient.Connect(5000);
except
//´íÎó´¦Àí
Application.MessageBox('ÎÞ·¨Á¬½Ó·þÎñÆ÷','ERROR',MB_ICONERROR);
FClient.Free;
exit;
end;
//**½ÓÊÕ·þÎñÆ÷ÐÅÏ¢**//
TransforCount:=(SendBytes-1) div packsize +1;//ÐèÒª´«ÊäTransforCount¸öÊý¾Ý¿é
Transfor_T:=SendBytes-(TransforCount-1)*packsize;//β°Í
ThreadForm.Instructor.Max:=TransforCount;
Snd.F2:=TransforCount; Snd.ID:=0;//֪ͨ·þÎñÆ÷½¨Á¢Îļþ
TP:=PSnd;
Inc(TP,32);
FileName:=ExtractFileName(ThreadForm.Edit2.Text);
Snd.Len:=Length(FileName)+1;
Snd.F1:=ThreadForm.FileSize;
UP:=@FileName;
move(UP^,TP^,Snd.Len);
FClient.Socket.Send(PSnd^,Snd.Len+32);//֪ͨ·þÎñÆ÷
repeat
process;
until
Rev.ID=3;//Snd.F1=Snd.F2;
SentBytes:=SentBytes+Snd.Len;//×îºóÒ»¸öβ°Í// Form1.MonitorThread.Terminate;
Snd.ID:=3;//¸æÖª·þÎñÆ÷¹Ø±ÕÄÚ´æÓ°Ïñ
Snd.Len:=0;
FClient.Socket.Send(PSnd^,32);
UnMapViewOfFile(ThreadForm.MP);//¹Ø±ÕÄÚ´æÓ³Ïñ CloseHandle(ThreadForm.Event);
// ThreadForm.Event;
ThreadForm.Button1.Enabled:=True; FClient.Disconnect;end;procedure TSocketThread.Process;
var
Bytes:Integer;
begin
IF RemainBytes>0 then//Éϴλ¹ÓÐ×Ö½ÚûÊÕÈ¡ //Ó¦¸Ã³õʼ»¯
begin
ReceivedCounter:=ReceivedCounter-RemainBytes;
IF ReceivedCounter>0 then//½ÓÊÕÊ£Óà×Ö½ÚºóÊý¾Ý±¨ÉÐδÍê³É½ÓÊÕ
begin
Bytes:=RemainBytes;//½ÓÊÕÊ£Óà
RemainBytes:=0;
end
else
begin
IF ReceivedCounter=0 then//Ê£Óà×ֽڸպýÓÊÕÍê³É
begin
Bytes:=RemainBytes;
RemainBytes:=0;
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;//Èç¹ûÍ·Íê³É¾ÍÊÇÌåÍê³É£¬·ñÔòÖ»ÊÇÍ·Íê³É
PushTransporting:=True;
end;
end
else
begin //Ê£Óà×Ö½Ú³¬¹ý±¾Êý¾Ý±¨´óС£¬²úÉúÊý¾ÝÕ³Á¬
Bytes:=ReceivedCounter+RemainBytes;
RemainBytes:=RemainBytes-Bytes;//Íê³É±¾Êý¾Ý±¨ºóÊ£Óà×Ö½Ú
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;//Èç¹ûÍ·Íê³É¾ÍÊÇÌåÍê³É£¬·ñÔòÖ»ÊÇÍ·Íê³É
PushTransporting:=True;
end;
end;
end;
FClient.ReadBuffer(TempPointer^,Bytes);
Inc(TempPointer,Bytes);
IF (Rev.Len=0) and HeaderFinished then//ֻҪͷ
begin
HeaderFinished:=False;
PushTransporting:=False;
TempPointer:=PRev;
ReceivedCounter:=32;//×¼±¸ÏÂÒ»¸öÍ·
Branch;//·ÖÖ§´¦Àí
end
else
begin
IF PushTransporting then //ÕýÔÚ´«Êäbody
begin
PushTransporting:=False;
ReceivedCounter:=Rev.Len;
end
else
IF BodyFinished then
begin
TempPointer:=PRev;
HeaderFinished:=False;
BodyFinished:=False;
ReceivedCounter:=32;//×¼±¸ÏÂÒ»¸öÍ·
Branch;//·ÖÖ§´¦Àí
end
end;
end
else
begin//RemainBytes=0
Try
RemainBytes:=FClient.ReadFromStack(True,15000,True);
Except
exit;
end;
end;
end;procedure TSocketThread.Branch;
begin
case Rev.ID of
1:ServerReady;
2:transporting;
end;
end;procedure TSocketThread.ServerReady;
begin
RequestTransfer;
Form1.MonitorThread:=TMonitorThread.Create;
end;procedure TSocketThread.RequestTransfer;
begin
Snd.ID:=1;
Snd.F1:=0;
Snd.Len:=0;
FClient.Socket.Send(PSnd^,32);
end;procedure TSocketThread.transporting;
var
FTT,FUU:PByte;
begin
SentBytes:=SentBytes+Snd.Len;//ÒÑ·¢ËÍ×Ö½Ú
Snd.ID:=2;
Snd.F1:=Rev.F1;
IF Snd.F1=Snd.F2 then
Snd.Len:=Transfor_T
else
Snd.Len:=packsize;
Snd.F3:=(Snd.F1-1)*packsize;
FTT:=FileMapPointer;
INC(FTT,(Snd.F1-1)*packsize);
FUU:=PSnd;
Inc(FUU,32);
move(FTT^,FUU^,Snd.Len);
FClient.Socket.Send(PSnd^,Snd.Len+32);
ThreadForm.Instructor.StepIt;
end;constructor TMonitorThread.Create;
begin
inherited Create(false);
SecondTimer:=0;
end;
procedure TMonitorThread.Execute;
var
H,I,V:DWord;
begin
{ While Not(Terminated) do
begin
Sleep(1000);
SecondTimer:=SecondTimer+1;
H:=0;
For I:=0 to ThreadCount-1 do
H:=H+SentBytes[I];
V:=H div SecondTimer;
V:=V div 1024;
Form1.StatusBar1.Panels[2].Text:='ƽ¾ùËÙÂÊ:'+Inttostr(V)+'KB/S';
end; }
end;end.
unit uUpdate;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient;const
packsize=65000;//包大小type
TRevBuffer=packed record
masmID:Word;//未用
ID:Word;//标记
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;
MD:Int64;
end;
TSendBuffer=packed record
masmID:Word;//未用
ID:Word;//标记
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;//数据区大小
MD:Int64;//摘要
buffer:Array[0..packsize-1] of byte;
end;//性能监测线程
type
TMonitorThread = class(TThread)
private
SecondTimer:DWord;
protected
procedure Execute; override;
public
constructor Create; reintroduce;
end;type
TForm1 = class;
TSocketThread = class(TThread)
private
Rev:TRevBuffer;
Snd:TSendBuffer;
PRev,PSnd,TP,UP:PByte;
TempPointer:PByte;
RemainBytes:Word;
ReceivedCounter:Integer;
HeaderFinished,BodyFinished,PushTransporting:Boolean; ThreadForm : TForm1;
FClient:TIdTCPClient;
SendBytes:DWord;//改线程要传输的字节数
FileMapPointer:PByte;//内存映象文件指针
TransforCount,Transfor_T:DWord;
procedure Process;
procedure Branch;
procedure RequestTransfer;
procedure ServerReady;
procedure Transporting;
protected
procedure Execute; override;
public
constructor Create(F: TForm1;Count:DWord;FileMap:PByte); reintroduce;
end;
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Label1: TLabel;
Label3: TLabel;
Edit1: TEdit;
Edit2: TEdit;
btnChoice: TButton;
Button1: TButton;
procedure btnChoiceClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
FileSize:DWord;//要传输的文件大小
Instructor:TProgressBar;
MP:PByte;
SocketThread:TSocketThread;
Event:THandle;
MonitorThread:TMonitorThread;
{ Public declarations }
end;var
Form1: TForm1; var
SentBytes:LongWord;
implementation{$R *.dfm}constructor TSocketThread.Create(F: TForm1;Count:DWord;FileMap:PByte);
begin
inherited Create(false);
ThreadForm := F;
SendBytes:=Count;
FileMapPointer:=FileMap;
SentBytes:=0;
ReceivedCounter:=32;
PRev:=@Rev;
PSnd:=@Snd;
TempPointer:=PRev;
end;procedure TForm1.btnChoiceClick(Sender: TObject);
var
F:Tsearchrec;
begin
IF OpenDialog1.Execute then
Edit2.Text:=OpenDialog1.FileName;
IF FindFirst(Edit2.Text,FaAnyfile,F)=0 then
FileSize:=F.Size;
end;procedure TForm1.Button1Click(Sender: TObject);
var
H,I,J,K,U:Integer;
FH,MH:THandle;
begin
//建立文件内存映象
// Button1.Enabled:=False;
FH:=FileOpen(Edit2.Text,fmOpenRead);
MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil);
CloseHandle(FH);
MP:=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);
CloseHandle(MH);
If Instructor<>nil then
Instructor.Free;
Instructor:=TProgressBar.Create(self);
Instructor.Left:=0;
Instructor.Top:=Edit2.Top+Edit2.Height+15;
Instructor.Width:=424;
Instructor.Step:=1;
Instructor.Parent:=Form1; SocketThread:=TSocketThread.Create(self,FileSize,MP);
Event:=CreateEvent(nil,False,False,nil);
end;procedure TSocketThread.Execute;
var
H,I,J:Integer;
Thread_L:Integer;
CurPointerOffset:DWord;
FileName:String[255];
begin
FClient:=TIdTCPClient.Create(nil);
FClient.Host:=ThreadForm.Edit1.Text;
FClient.Port:=10888;
try
FClient.Connect(5000);
except
//错误处理
Application.MessageBox('无法连接服务器','ERROR',MB_ICONERROR);
FClient.Free;
exit;
end;
//**接收服务器信息**//
TransforCount:=(SendBytes-1) div packsize +1;//需要传输TransforCount个数据块
Transfor_T:=SendBytes-(TransforCount-1)*packsize;//尾巴
ThreadForm.Instructor.Max:=TransforCount;
Snd.F2:=TransforCount; Snd.ID:=0;//通知服务器建立文件
TP:=PSnd;
Inc(TP,32);
FileName:=ExtractFileName(ThreadForm.Edit2.Text);
Snd.Len:=Length(FileName)+1;
Snd.F1:=ThreadForm.FileSize;
UP:=@FileName;
move(UP^,TP^,Snd.Len);
FClient.Socket.Send(PSnd^,Snd.Len+32);//通知服务器
repeat
process;
until
Rev.ID=3;
SentBytes:=SentBytes+Snd.Len;//最后一个尾巴// Form1.MonitorThread.Terminate;
Snd.ID:=3;//告知服务器关闭内存映象
Snd.Len:=0;
FClient.Socket.Send(PSnd^,32);
UnMapViewOfFile(ThreadForm.MP);//关闭内存映象
CloseHandle(ThreadForm.Event);
// ThreadForm.Event;
ThreadForm.Button1.Enabled:=True; FClient.Disconnect;end;
var
Bytes:Integer;
begin
IF RemainBytes>0 then//上次还有字节未收取
begin
ReceivedCounter:=ReceivedCounter-RemainBytes;
IF ReceivedCounter>0 then//接收剩余字节后数据报尚未完成接收
begin
Bytes:=RemainBytes;//接收剩余
RemainBytes:=0;
end
else
begin
IF ReceivedCounter=0 then//剩余字节刚好接收完成
begin
Bytes:=RemainBytes;
RemainBytes:=0;
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;// 如果头完成,则是体完成,否则则是头完成
PushTransporting:=True;
end;
end
else
begin //剩余字节超过本数据报大小,产生数据粘连
Bytes:=ReceivedCounter+RemainBytes;
RemainBytes:=RemainBytes-Bytes;//完成本数据报后剩余字节数
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;// 如果头完成,则是体完成,否则则是头完成
PushTransporting:=True;
end;
end;
end;
FClient.ReadBuffer(TempPointer^,Bytes);
Inc(TempPointer,Bytes);
IF (Rev.Len=0) and HeaderFinished then//只要头
begin
HeaderFinished:=False;
PushTransporting:=False;
TempPointer:=PRev;
ReceivedCounter:=32;//准备下一个头
Branch;//分支处理
end
else
begin
IF PushTransporting then //正在传输Body
begin
PushTransporting:=False;
ReceivedCounter:=Rev.Len;
end
else
IF BodyFinished then
begin
TempPointer:=PRev;
HeaderFinished:=False;
BodyFinished:=False;
ReceivedCounter:=32;//准备下一个头
Branch;//分支处理
end
end;
end
else
begin//RemainBytes=0
Try
RemainBytes:=FClient.ReadFromStack(True,15000,True);
Except
exit;
end;
end;
end;procedure TSocketThread.Branch;
begin
case Rev.ID of
1:ServerReady;
2:transporting;
end;
end;procedure TSocketThread.ServerReady;
begin
RequestTransfer;
Form1.MonitorThread:=TMonitorThread.Create;
end;procedure TSocketThread.RequestTransfer;
begin
Snd.ID:=1;
Snd.F1:=0;
Snd.Len:=0;
FClient.Socket.Send(PSnd^,32);
end;procedure TSocketThread.transporting;
var
FTT,FUU:PByte;
begin
SentBytes:=SentBytes+Snd.Len;//已发送字节
Snd.ID:=2;
Snd.F1:=Rev.F1;
IF Snd.F1=Snd.F2 then
Snd.Len:=Transfor_T
else
Snd.Len:=packsize;
Snd.F3:=(Snd.F1-1)*packsize;
FTT:=FileMapPointer;
INC(FTT,(Snd.F1-1)*packsize);
FUU:=PSnd;
Inc(FUU,32);
move(FTT^,FUU^,Snd.Len);
FClient.Socket.Send(PSnd^,Snd.Len+32);
ThreadForm.Instructor.StepIt;
end;constructor TMonitorThread.Create;
begin
inherited Create(false);
SecondTimer:=0;
end;procedure TMonitorThread.Execute;
var
H,I,V:DWord;
begin
{ While Not(Terminated) do
begin
Sleep(1000);
SecondTimer:=SecondTimer+1;
H:=0;
For I:=0 to ThreadCount-1 do
H:=H+SentBytes[I];
V:=H div SecondTimer;
V:=V div 1024;
Form1.StatusBar1.Panels[2].Text:='ƽ¾ùËÙÂÊ:'+Inttostr(V)+'KB/S';
end; }
end;end.
unit uUpdate;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPServer, ComCtrls;const packsize=65000;
var
FileMapPointer:PByte;
FileSize:LongWord;
FN:String[250];type TSend=packed record
masmID:Word;
ID:Word;
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;
MD:Int64;
end;
type TReceive=packed record
masmID:Word;
ID:Word;
F1:DWord;
F2:DWord;
F3:DWord;
F4:DWord;
Len:DWord;
MD:Int64;
Buffer:Array[0..packsize-1] of byte;
end;type
TForm1 = class;
TSocketProcesser=Class
private
AOne:TidPeerThread;
HeaderFinished,BodyFinished,PushTransporting:Boolean;
RemainBytes:Word;
ReceivedCounter:Integer;//要接收的字节数
Rev:TReceive;
Snd:TSend;
PRev,PSnd:PByte;
TempPointer:PByte;
procedure Branch;//处理
procedure Echo(Option:Word);
procedure BuildFile;//建立文件内存映象
procedure Pass;//通知客户端可以传输
procedure FileTransport;
public
frm:TForm1;
constructor Create(AThread:TidPeerThread;F:TForm1);reintroduce;
procedure Process;
end;
TForm1 = class(TForm)
Memo1: TMemo;
IdTCPServer1: TIdTCPServer;
Button1: TButton;
Button2: TButton;
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
Instructor:TProgressBar;
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
DoP:TSocketProcesser;
begin
DoP:=TSocketProcesser.Create(AThread,self);
Athread.Data:=Dop;
end;procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
TSocketProcesser(AThread.Data).Free;
AThread.Data:=Nil;
end;procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
TSocketProcesser(AThread.Data).Process;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
IF IdTCPServer1.Active then
begin
IdTCPServer1.Active:=False;
Button1.Caption:='启动服务';
end
else
begin
IdTCPServer1.Active:=True;
Button1.Caption:='终止服务';
end;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
IdTCPServer1.Active:=False;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Lines.Clear;
end;procedure TSocketProcesser.Branch;
begin
case Rev.ID of
0: BuildFile;
1: Pass;
2: FileTransport;
3:
begin
UnMapViewOfFile(FileMapPointer);//关闭文件
Form1.Memo1.Lines.Add(FN+','+TimeToStr(now())+'结束传输');
end;
end;
end;procedure TSocketProcesser.BuildFile;
var
FileName:String[250];
PS,PD:PByte;
FH1,FH2:THandle;
size:DWord;
str:string;
begin
PS:=TempPointer;
Inc(PS,32);
PD:=@FileName;
move(PS^,PD^,Rev.Len);
FN:=FileName;
size:=Rev.F1;//得到文件长度
str:=ExtractFilePath(Application.ExeName);
if not DirectoryExists(str + 'Files\') then
CreateDir(str + 'Files\');
FH1:=FileCreate(str+'files\'+FileName);
FileClose(FH1);
FH1:=FileOpen(str+'files\'+FileName,fmOpenreadWrite);
FH2:=CreateFileMapping(FH1,nil,Page_ReadWrite,0,size,nil);
CloseHandle(FH1);
FileMapPointer:=MapViewOfFile(FH2,File_Map_All_Access,0,0,size);
FileSize:=size;//
CloseHandle(FH2);
Form1.Memo1.Lines.Add(FileName+'长度'+inttostr(FileSize)+','+TimetoStr(Now())+'开始传输');
Echo(1);
end;
begin
Snd.F1:=Rev.F1+1;//下一个数据报
Snd.F2:=Rev.F2;
Echo(2);
end;procedure TSocketProcesser.FileTransport;
var
TempFileMapPointer,PB:PByte;
begin
TempFileMapPointer:=FileMapPointer;
PB:=PRev;
Inc(TempFileMapPointer,Rev.F3);
Inc(PB,32);
move(PB^,TempFileMapPointer^,Rev.Len);
IF Rev.F1<Rev.F2 then//请求下一个数据报
Pass
else//如果相等,则接收完毕
Echo(3);
end;constructor TSocketProcesser.Create(AThread:TidPeerThread;F:TForm1);
begin
inherited Create;
frm:=F;
AOne:=AThread;
ReceivedCounter:=32;//首先接收32字节
HeaderFinished:=False;
BodyFinished:=False;
PushTransporting:=False;
RemainBytes:=0;
PRev:=@Rev;
PSnd:=@Snd;
TempPointer:=PRev;
end;procedure TSocketProcesser.Process;
var
Bytes:Integer;
begin
IF ReceivedCounter=0 then
exit;
IF RemainBytes>0 then//上次还有字节未收取
begin
ReceivedCounter:=ReceivedCounter-RemainBytes;
IF ReceivedCounter>0 then//接收剩余字节后数据报尚未完成接收
begin
Bytes:=RemainBytes;//接收剩余
RemainBytes:=0;
end
else
begin
IF ReceivedCounter=0 then//剩余字节刚好接收完成
begin
Bytes:=RemainBytes;
RemainBytes:=0;
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;//如果头完成则是体完成,否则只是头完成
PushTransporting:=True;
end;
end
else
begin //剩余字节超过本数据报大小,产生数据粘连
Bytes:=ReceivedCounter+RemainBytes;
RemainBytes:=RemainBytes-Bytes;//完成本数据报后剩余字节
IF HeaderFinished then
BodyFinished:=True
else
begin
HeaderFinished:=True;//如果头完成则体完成,否则只是头
PushTransporting:=True;
end;
end;
end;
AOne.Connection.ReadBuffer(TempPointer^,Bytes);
Inc(TempPointer,Bytes);
frm.Instructor.StepIt;
IF (Rev.Len=0) and HeaderFinished then//只要头
begin
HeaderFinished:=False;
PushTransporting:=False;
TempPointer:=PRev;
ReceivedCounter:=32;//准备下一个头
Branch;//分支处理
end
else
begin
IF PushTransporting then //正在传输body
begin
PushTransporting:=False;
ReceivedCounter:=Rev.Len;
end
else
IF BodyFinished then
begin
TempPointer:=PRev;
HeaderFinished:=False;
BodyFinished:=False;
ReceivedCounter:=32;//准备下一个头
Branch;//分支处理
end
end;
end
else
begin
Try
RemainBytes:=AOne.Connection.ReadFromStack(True,15000,True); {//返回本次要传输的字节大小(不是文件大小)}
Except
exit;
end;
end;
end;procedure TSocketProcesser.Echo(Option: Word);
begin
Snd.ID:=Option;
Snd.Len:=0;
AOne.Connection.Socket.Send(PSnd^,32);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
If Instructor<>nil then
Instructor.Free;
Instructor:=TProgressBar.Create(self);
Instructor.Left:=8;
Instructor.Top:=Memo1.Top+Memo1.Height+10;
Instructor.Width:=400;
Instructor.Step:=1;
Instructor.Parent:=Form1;
end;end.
[email protected]
[email protected]
我没做过ftp这方面的东东,
你有没有代码,如果有能不能给我一份
[email protected]