TIdFtpServer的多线程如何做?(60分)

  • 主题发起人 主题发起人 icysword
  • 开始时间 开始时间
I

icysword

Unregistered / Unconfirmed
GUEST, unregistred user!
写了个只能单线程下载的... 请问多线程该怎么做?
 
server本来就是多线程的,每连接一个线程,怎么会有如此一问?
贴出你的代码!
 
procedure TForm1.FtpListDirectory(ASender: TIdFTPServerThread;
const APath: String; ADirectoryListing: TIdFTPListItems);
var
fi:WIN32_FIND_DATA;
h:integer;
begin
ADirectoryListing.ListFormat:=flfDos;
ASender.CurrentDir:=path;
h:=FindFirstFile(pchar(path+'*.*'),fi);
while h<>-1 do
begin
if not IsDirNotation(path+fi.cFileName) then
begin
if fi.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY<>FILE_ATTRIBUTE_DIRECTORY then
with ADirectoryListing.Add do
begin
ItemType:=ditFile;
FileName:=fi.cFileName;
Size:=fi.nFileSizeLow;
ModifiedDate:=now;
end
else
with ADirectoryListing.Add do
begin
ItemType:=ditDirectory;
FileName:=fi.cFileName;
Size:=fi.nFileSizeLow;
ModifiedDate:=now;
end;
end;
if not FindNextFile(h,fi) then
h:=-1;
end;
end;

procedure TForm1.FtpGetFileSize(ASender: TIdFTPServerThread;
const AFilename: String; var VFileSize: Int64);
var
h:dword;
begin
h:=CreateFile(pchar(AFilename),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
VFileSize:=GetFileSize(h,nil);
CloseHandle(h);
end;

procedure TForm1.FtpChangeDirectory(ASender: TIdFTPServerThread;
var VDirectory: String);
begin
ASender.CurrentDir := VDirectory;
end;

procedure TForm1.FtpRetrieveFile(ASender: TIdFTPServerThread;
const AFileName: String; var VStream: TStream);
begin
VStream := TFileStream.Create(AFileName,fmShareDenyNone or fmOpenRead);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ftp.Threads.Clear;
end;

就是这些了,, 用flashget拉, 只有一个线程., 多开也拉不了.
 
对于FTP SERVER我没作过,但是有一点要注意,FTPSREVER继承于IDTCPSERVER,
他的ASENDER是对每一个连接产生的线程,因此所有的连接产生的线程都将执行
相同的procedure 。
FTP 的多线程下载应该是将文件大小分段,每线程都取下载指定范围的内容。
在你的FTPretrievefile中,都是将整个文件流返回给每个连接,相必是不行的了。
应该想办法得知每连接请求传输的文件范围,然后将该范围的内容返回给该连接。
 
procedure TForm1.FtpRetrieveFile(ASender: TIdFTPServerThread;
const AFileName: String; var VStream: TStream);
begin
VStream := TFileStream.Create(AFileName,fmShareDenyNone or fmOpenRead);
end;

这里用ASender线程来判断客户端请求的文件指针? 该怎么做?
 
看了一下FTPSERVER的原代码,即把你的VStream发给客户端,对于断点续传,
在retr命令前客户端会有一个rest命令通知服务端从哪个位置开始传送(即设置
sender.restpos),当服务端接收RETR命令后,会将你的VSTREAM。Position设置
为restpos,然后从VASTREAM的POSITION开始发送数据。这些操作都是自动的。
但问题出在发送的地方:在TIdDataChannelThread.Run中他是
FDataChannel.WriteStream(TStream(Data));
writestream如果没有其他参数,他将会发送整个STREAM,而不是从STREAM。POSITION
开始,所以这个地方应该是writestream(TSTream(Data),false);即不发送整个STREAM,
而是从STREAM的当前位置开始发送。
所以对于IDFTPSERVER可能你需要修改一下这个代码才行(需要重新编译一下INDY原代码)
 
后退
顶部