讨论:flash get 的原理 ( 积分: 50 )

  • 主题发起人 主题发起人 xgwzw
  • 开始时间 开始时间
X

xgwzw

Unregistered / Unconfirmed
GUEST, unregistred user!
,当多个线程同时写文件时,需要保存每个线程的开始位置,然后下载完后,怎样删除这些信息,我将这些信息放到临时文件的尾部,下载后怎样删除呢
鼠标点击右键时,如何获取url?
 
,当多个线程同时写文件时,需要保存每个线程的开始位置,然后下载完后,怎样删除这些信息,我将这些信息放到临时文件的尾部,下载后怎样删除呢
鼠标点击右键时,如何获取url?
 
使用TRUNCATE,DELPHI帮助就有这样的例子
var

f: fileof Integer;
i,j: Integer;
begin
AssignFile(f,'TEST.INT');
Rewrite(f);
for i := 1 to 6 do
Write(f,i);
Writeln('File before truncation:');
Reset(f);
while not Eof(f) do
begin
Read(f,i);
Writeln(i);
end;
Reset(f);
for i := 1 to 3 do
Read(f,j); { Read ahead 3 records }
Truncate(f); { Cut file off here }

Writeln;
Writeln('File after truncation:');
Reset(f);
while not Eof(f) do
begin
Read(f,i);
Writeln(i);
end;
CloseFile(f);
Erase(f);
end;
 
>>...我将这些信息放到临时文件的尾部...
FlashGet不是将这些信息附加到文件尾部,而是放在它自己的数据库文件中(.jcd)
删除附加的文件尾其实很简单,调用FileSeek和SetEndOfFile函数即可,首先用FileSeek移动文件指针到你准备结束的位置(比如,当前文件有1028K,你Seek到1024K的位置),然后调用SetEndOfFile即可从1024k位置截断文件,后面的数据就删除掉了!
 
临时文件也一样,不过不是加到尾部,而是用一行来记录这个进程的下载进度
就像BitComet一样,BitComet是用XML文件来记录下载块的,你打开那个XML文件看看就明白了
 
这个问题挺有趣
flash get是delphi编写的么?
如果我们用indy控件写出一个类似flash get的软件,效率比的上原软件么?
关注。。。
 
多线程写文件时要不要同步呢
如果要同步的话,那岂不是相当于单线程,由于线程的调度在单CPU上或许更慢
 
当然要同步,否则会I/O冲突

你可以用缓存,然后多线程下载单线程写入
 
to hs-kill
缓存怎么用法 举个例子或demo的
谢谢!
 
demo暂时是没有。。。

其实说缓存。。。其实就是每个线程下载的时候都下载到内存流里,设置每次写入时的块大小,比如200k/块

然后独立有个线程将已下载完的内存流数据写到文件里,一个线程下载完一块后就调用写入线程的保存方法,写入线程就把这部分数据写到文件里,用临界区来控制不会在一块数据被写入时另一块数据也请求写

由于写入数据比下载数据耗费的时间要短的多,所以基本每个线程都不会有过多的等待数据写入时间,当然,这也取决于你的线程数量以及块大小,还有当前网络速度
 
FlashGet是用C++写的。
我觉得用现有Delphi的控件很难完全实现FlashGet的下载功能。首先,现在我们用的是Indy组建,它只能写入文件或者写入流,而且对于多线程同时分段下载一个文件,它不是很适合使用。在这方面我们必须自己写一套支持多线程同时分段下载文件的类。同时,现在的流类也不适合在类似FlashGet这样的软件中用,因为要么这个流是写入内存的,要么是写入文件的。写入内存肯定是我们选择的。但是一个线程对应一个流,那么如果我们设定下载5M以后再写入磁盘,那么究竟是单个线程下载5M写入还是总共下载5M数据就写入磁盘呢?FlashGet是多线程,每个线程负责下载一段,同时它又是多任务的,可以同时下载多个软件,显然在下载数据的计算和速度限制方面普通的流类已经不足以满足要求 。只能是做一个新的流类,该类支持多线程甚至多项目同时存取流信息在一块内存中,这样当这块内存满了就按照标记分别写入多个文件的多个位置,接着继续接收下面收到的数据。这个类有点类似缓存或者是“虚拟磁盘”呵呵,打引号的,因为只是将多段数据缓存在一个内存块里面。我觉得这样的设计应该是FlashGet采用的

[:D]我仅仅是猜测的:)不过如果我要写FlashGet我会采取这种方法。大家如果有更好的方法也欢迎拿出来一起讨论:)
 
我前一阵的项目有需要多线程下载的,所以就写了个,当然最后没搞出来T_T,对于小文件可以,大文件总是会停住失去连接。。。。
由于当时时间紧没再去研究,另外一个人用VB写了一个多线程下载的,基本实现了FG的多任务多线程下载功能。。。。速度嘛。。我感觉不比FG慢多少。。。。所以就用那个了

实际的实现方法就是按我上面说的。。。

每个任务至少有2个线程,一个是负责写文件的,其他的是负责下载。。

zqw0117说的5M的问题。。也许我想的没那么深,我认为应该是每个下载线程下载了5M后申请写入文件,而不是总体的

如果你要下载3个任务,每个任务10个线程,那一共就要开33个线程喽~别看这么多,实际上是很快的
 
GET 请求就可以了,流同步也可,不同步分开存,最后统一合并就可以了。
 
呵呵!flashget完全可以用delphi重写。
往硬盘写文件还用考虑这么多?windows这么牛叉的内存影像文件功能怎么不用?管你几十个G的文件,全部影像在内存中,只要移动指针填字节就可以了,可以成千个指针一起工作~~~,其余复杂的虚拟算法操作系统全包圆咯!
 
to masm
多个线程同时写文件 内存影像文件有这样的demo吗
谢谢
 
procedure TForm1.Button1Click(Sender: TObject);
var
FH,MH,DH1,DH2,DH3:THandle;
YSize,I,J,AAA,BBB:DWord;
P1,P2,P3,P4:^Byte;
begin
if not FileExists('G:/delphi7/delphi7.rar') then
raise Exception.Create('文件没找到!!')
else
FH:=FileOpen('G:/delphi7/delphi7.rar',fmOpenRead);
YSize:=GetFileSize(FH,nil);
MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,Ysize,nil);
CloseHandle(FH);
P1:=MapViewOfFile(MH,File_Map_Read,0,0,YSize);
P3:=P1;
CloseHandle(MH);
//建立影像
DH1:=FileCreate('A.rar');
FileClose(DH1);
DH1:=FileOpen('A.rar',fmOpenreadWrite);
DH2:=CreateFileMapping(DH1,nil,Page_ReadWrite,0,YSize,nil);
CloseHandle(DH1);
P2:=MapViewOfFile(DH2,File_Map_All_Access,0,0,YSize);
CloseHandle(DH2);
P4:=P2;
ProgressBar1.Max:=YSize;
J:=0;
AAA:=GetTickCount();
For I:=1 to YSize do
begin
P2^:=P1^;
INC(P1);
INC(P2);
Inc(J);
IF J=300000 then
begin
ProgressBar1.Position:=I;
J:=0;
end;
end;
ProgressBar1.Position:=YSize;
BBB:=(GetTickCount()-AAA) div 1000;
Label1.Caption:=InttoStr(BBB);
UnMapViewOfFile(P3);
UnMapViewOfFile(P4);
end;
这是我自己拷贝文件测试用的,改成多线程很简单的。
 
to masm
谢谢
我看一下
 
to masm
不是很懂 p3,p4 是干什么用的
怎么没有用到
 
这只是复制文件啊。。。。
而且 对于复制文件。。。。。单线程比多线程效率要高的多

之所以用多现成就是因为从网络节点(数据源)获得数据的过程要比写数据慢的多,所以用多线程可以减少这种数据等待的时间

而对于磁盘的数据复制。。本来读写的速度就差不多,你还开个多线程,等于增加了磁盘寻道的时间,相对效率反而降低了
 
自由界面和报表的完美解决方案!
http://www.anylib.com
 
后退
顶部