unit Unit1;<br><br>interface<br><br>uses<br> {}filectrl,inifiles,{}Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> Dialogs, StdCtrls, ScktComp, ExtCtrls;<br><br>type<br> Tbuf_char=array[0..4095] of char;<br> Tbuf_byte=array[0..4095] of byte;<br><br>type<br> TForm1 = class(TForm)<br> ClientSocket1: TClientSocket;<br> Memo1: TMemo;<br> Panel1: TPanel;<br> Edit1: TEdit;<br> Button1: TButton;<br> Edit2: TEdit;<br> Button3: TButton;<br> Button4: TButton;<br> Label2: TLabel;<br> Label3: TLabel;<br> Label1: TLabel;<br> procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);<br> procedure Button1Click(Sender: TObject);<br> procedure ClientSocket1Connect(Sender: TObject;<br> Socket: TCustomWinSocket);<br> procedure Edit1Change(Sender: TObject);<br> procedure FormCreate(Sender: TObject);<br> procedure Edit2Change(Sender: TObject);<br> procedure Button3Click(Sender: TObject);<br> procedure Button4Click(Sender: TObject);<br> private<br> { Private declarations }<br> public<br> { Public declarations }<br> filename1:string; //本地文件名<br> serfilename:string; //服务器端文件名<br> serhost1:string; //服务器地址<br> can_rec1:boolean; //是否可以接收<br> stop1:boolean; //是否停止<br><br> end;<br><br>var<br> Form1: TForm1;<br> pos1:longint; //上次下载到的位置<br><br><br>implementation<br><br><br>{$R *.dfm}<br><br>function app_path1:string;<br>begin<br> result:=extractfilepath(application.ExeName);<br>end;<br><br><br>//接收一行数据//socket,超时,结束符<br>function socket_rec_line1(socket1:TCustomWinSocket;timeout1:integer;crlf1:string=#13#10):string;<br>var<br> buf1:Tbuf_char;<br> r1:integer;<br> ts1:TStringStream; //保存所有的数据<br><br> FSocketStream: TWinSocketStream;<br><br>begin<br><br> ts1:=TStringStream.Create('');<br> FSocketStream:= TWinSocketStream.create(Socket1, timeout1);<br><br><br> //while true do//下面的一句更安全,不过对本程序好象没起作用<br> while (socket1.Connected=true) do<br> begin<br><br> //确定是否可以接收数据<br> //只能确定接收的超时,可见WaitForData的源码<br> if not FSocketStream.WaitForData(timeout1) then break; //continue;<br><br> //这一句是一定要有的,以免返回的数据不正确<br> zeromemory(@buf1,sizeof(buf1));<br> r1 := FsocketStream.Read(buf1, 1); //每次只读一个字符,以免读入了命令外的数据<br> //读不出数据时也要跳出,要不会死循环<br> if r1=0 then break; //test<br> //用FsocketStream.Read能设置超时<br> //r1:=socket1.ReceiveBuf(buf1,sizeof(buf1));<br> ts1.Write(buf1,r1);<br><br> //读到回车换行符了<br> if pos(crlf1,ts1.DataString)<>0 then<br> begin<br> break;<br> end;<br><br> end;<br><br> result:=ts1.DataString;<br><br> //没有读到回车换行符,就表示有超时错,这时返回空字符串<br> if pos(crlf1,result)=0 then<br> begin<br> result:='';<br> end;<br><br> ts1.Free;<br> FSocketStream.Free;<br><br>end;<br><br><br> function get_host1(in1:string):string;<br> begin<br> in1:=trim(in1);<br> if pos('http://',lowercase(in1))=1 then<br> begin<br> in1:=copy(in1,length('http://')+1,length(in1));<br> end;<br> if pos('/',in1)<>0 then<br> begin<br> in1:=copy(in1,0,pos('/',in1)-1);<br> end; <br> result:=in1;<br> end;<br><br> function get_file1(in1:string):string;<br> begin<br> in1:=trim(in1);<br> if pos('http://',lowercase(in1))=1 then<br> begin<br> in1:=copy(in1,length('http://')+1,length(in1));<br> end;<br> if pos('/',in1)<>0 then<br> begin<br> in1:=copy(in1,pos('/',in1)+1,length(in1));<br> end; <br> result:=in1;<br><br> end;<br><br>procedure TForm1.ClientSocket1Read(Sender: TObject;<br> Socket: TCustomWinSocket);<br>begin<br> memo1.Lines.Add(socket.ReceiveText);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> url1:string;<br> buf1:Tbuf_byte;<br> rec1:longint;<br> f1:file;<br><br> cmd1:string; //这一行的内容<br> reclen1,real_reclen1:longint; //服务器返回的长度;实际已经收到的长度<br> value1:string; //标志们的值<br> total_len1:longint; //数据总长<br><br>begin<br> try<br><br> //self.filename1:='c:/temp1.dat';<br> assignfile(f1,self.filename1);<br> can_rec1:=false;<br> self.stop1:=false;<br><br> if FileExists(self.filename1)=true then<br> begin<br> reset(f1,1);<br> pos1:=filesize(f1);<br> end<br> else<br> begin<br> rewrite(f1,1);<br> pos1:=0;<br> end;<br><br> seek(f1,pos1);<br><br><br> ClientSocket1.Active:=false;<br> ClientSocket1.Host:=get_host1(edit1.Text);<br> ClientSocket1.Port:=80;<br><br><br> url1:='';<br><br> self.serfilename:=get_file1(edit1.Text);<br> self.serhost1:=get_host1(edit1.Text);<br><br> //取得文件长度以确定什么时候结束接收[通过"head"请求得到]<br><br> ClientSocket1.Active:=false;<br> ClientSocket1.Active:=true;<br> url1:='';<br> <br> url1:=url1+'HEAD /'+self.serfilename+' HTTP/1.1'+#13#10;<br><br> //不使用缓存,我附加的<br> //与以前的服务器兼容<br> url1:=url1+'Pragma: no-cache'+#13#10;<br> //新的<br> url1:=url1+'Cache-Control: no-cache'+#13#10;<br><br> //不使用缓存,我附加的_end;<br><br> url1:=url1+'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)'+#13#10;<br> //下面这句必须要有<br> //url1:=url1+'Host: clq.51.net'+#13#10;<br> url1:=url1+'Host: '+self.serhost1+#13#10;<br> url1:=url1+#13#10;<br> <br> ClientSocket1.Socket.SendText(url1);<br><br> while ClientSocket1.Active=true do<br> begin<br><br> if self.stop1=true then break;<br><br> cmd1:=socket_rec_line1(ClientSocket1.Socket,60*1000);<br><br> //计算文件的长度<br><br> if pos(lowercase('Content-Length: '),lowercase(cmd1))=1 then<br> begin<br> value1:=copy(cmd1,length('Content-Length: ')+1,length(cmd1));<br> total_len1:=strtoint(trim(value1));<br> end;<br><br> //计算文件的长度_end;<br><br> if cmd1=#13#10 then break;<br> end; <br><br> //取得文件长度以确定什么时候结束接收_end;<br><br> //发送get请求,以得到实际的文件数据<br><br> clientsocket1.Active:=false;<br> clientsocket1.Active:=true;<br><br> url1:='';<br><br> //url1:=url1+'GET http://clq.51.net/textfile.zip HTTP/1.1'+#13#10;<br> //url1:=url1+'GET /textfile.zip HTTP/1.1'+#13#10;<br> url1:=url1+'GET /'+self.serfilename+' HTTP/1.1'+#13#10;<br> url1:=url1+'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'+#13#10;<br> //应该可以不要url1:=url1+'Accept-Language: zh-cn'+#13#10;<br> //应该可以不要url1:=url1+'Accept-Encoding: gzip, deflate'+#13#10;<br><br> //不使用缓存,我附加的<br> //与以前的服务器兼容<br> //url1:=url1+'Pragma: no-cache'+#13#10;<br> //新的<br> //url1:=url1+'Cache-Control: no-cache'+#13#10;<br><br> //不使用缓存,我附加的_end;<br><br> url1:=url1+'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)'+#13#10;<br> //接受数据的范围,可选<br> //url1:=url1+'RANGE: bytes=533200-'+#13#10;<br> url1:=url1+'RANGE: bytes='+inttostr(pos1)+'-'+#13#10;<br> //下面这句必须要有<br> //url1:=url1+'Host: clq.51.net'+#13#10;<br> url1:=url1+'Host: '+self.serhost1+#13#10;<br> //应该可以不要<br> //url1:=url1+'Connection: Keep-Alive'+#13#10;<br> url1:=url1+#13#10;<br> ClientSocket1.Socket.SendText(url1);<br><br> while ClientSocket1.Active=true do<br> begin<br><br> if self.stop1=true then break;<br><br> cmd1:=socket_rec_line1(ClientSocket1.Socket,60*1000);<br><br> //是否可接收<br> if pos(lowercase('Content-Range:'),lowercase(cmd1))=1 then<br> begin<br> can_rec1:=true;<br> end;<br><br> //是否可接收_end;<br><br> //计算要接收的长度<br> <br> if pos(lowercase('Content-Length: '),lowercase(cmd1))=1 then<br> begin<br> value1:=copy(cmd1,length('Content-Length: ')+1,length(cmd1));<br> reclen1:=strtoint(trim(value1));<br> end;<br><br> //计算要接收的长度_end;<br><br> //头信息收完了<br> if cmd1=#13#10 then break;<br> end;<br><br> real_reclen1:=0;<br> while ClientSocket1.Active=true do<br> begin<br><br><br> if self.stop1=true then break;<br><br> //不能接收则退出<br> if can_rec1=false then break;<br><br> //如果文件当前的长度大于服务器标识的长度,则是出错了,不要写入文件中<br> if filesize(f1)>=total_len1 then<br> begin<br> showmessage('文件已经下载完毕了!');<br> break;<br> end;<br><br> zeromemory(@buf1,sizeof(buf1));<br> rec1:=ClientSocket1.Socket.ReceiveBuf(buf1,sizeof(buf1));<br><br> //如果实际收到的长度大于服务器标识的长度,则是出错了,不要写入文件中<br> if real_reclen1>=reclen1 then<br> begin<br> showmessage('文件已经下载完毕了!');<br> break;<br><br> end;<br> //如果当前的长度大于服务器标识的长度,则是出错了,不要写入文件中<br> if pos1=reclen1 then<br> begin<br> showmessage('文件已经下载完毕了!');<br> break;<br><br> end;<br><br> blockwrite(f1,buf1,rec1);<br><br> real_reclen1:=real_reclen1+rec1;<br><br> Label1.Caption:=FormatFloat('#,##',real_reclen1)+'/'+FormatFloat('#,##',reclen1);<br> Label1.Caption:=Label1.Caption+'->'+inttostr(trunc((real_reclen1/reclen1)*100))+'%';<br> application.ProcessMessages;<br><br><br><br> end;<br><br> closefile(f1);<br> showmessage('ok');<br><br> //发送get请求,以得到实际的文件数据_end;<br><br> ClientSocket1.Active:=false;<br> <br> except<br> closefile(f1);<br> showmessage('discon...');<br> end;<br><br><br>end;<br><br>procedure TForm1.ClientSocket1Connect(Sender: TObject;<br> Socket: TCustomWinSocket);<br>var<br> url1:string; <br>begin<br>{ url1:='';<br><br> url1:=url1+'GET http://clq.51.net/textfile.zip HTTP/1.1'+#13#10;<br> url1:=url1+'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'+#13#10;<br> //应该可以不要url1:=url1+'Accept-Language: zh-cn'+#13#10;<br> //应该可以不要url1:=url1+'Accept-Encoding: gzip, deflate'+#13#10;<br><br> //不使用缓存,我附加的<br> //与以前的服务器兼容<br> url1:=url1+'Pragma: no-cache'+#13#10;<br> //新的<br> url1:=url1+'Cache-Control: no-cache'+#13#10;<br><br> //不使用缓存,我附加的_end;<br><br> url1:=url1+'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)'+#13#10;<br> //接受数据的范围,可选<br> url1:=url1+'RANGE: bytes=533200-'+#13#10;<br> //下面这句必须要有<br> url1:=url1+'Host: clq.51.net'+#13#10;<br> url1:=url1+'Connection: Keep-Alive'+#13#10;<br> url1:=url1+#13#10;<br> ClientSocket1.Socket.SendText(url1);<br><br> }<br>end;<br><br>procedure TForm1.Edit1Change(Sender: TObject);<br>var<br> ini1:tinifile;<br>begin<br> ini1:=tinifile.Create(app_path1+'sys1.ini');<br> ini1.WriteString('file1','host1',edit1.Text);<br><br> ini1.Free;<br><br>end;<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>var<br> ini1:tinifile;<br>begin<br> ini1:=tinifile.Create(app_path1+'sys1.ini');<br> edit1.Text:=ini1.ReadString('file1','host1',edit1.Text);<br> self.filename1:=ini1.ReadString('file1','filename1','c:/temp1.dat');<br> edit2.Text:=self.filename1;<br> //pos1:=filesize(<br> ini1.Free;<br><br><br>end;<br><br>procedure TForm1.Edit2Change(Sender: TObject);<br>var<br> ini1:tinifile;<br>begin<br> ini1:=tinifile.Create(app_path1+'sys1.ini');<br> ini1.WriteString('file1','filename1',edit2.Text);<br><br> self.filename1:=edit2.Text;<br> ini1.Free;<br><br>end;<br><br>procedure TForm1.Button3Click(Sender: TObject);<br>var<br> url1:string;<br> buf1:Tbuf_byte;<br> rec1:longint;<br> f1:file;<br><br> cmd1:string; //这一行的内容<br> reclen1,real_reclen1:longint; //服务器返回的长度;实际已经收到的长度<br> value1:string; //标志们的值<br><br>begin<br> self.stop1:=false;<br><br> ClientSocket1.Active:=false;<br> ClientSocket1.Host:=get_host1(edit1.Text);<br> ClientSocket1.Port:=80;<br> ClientSocket1.Active:=true;<br><br> url1:='';<br><br> self.serfilename:=get_file1(edit1.Text);<br> self.serhost1:=get_host1(edit1.Text);<br> //url1:=url1+'GET http://clq.51.net/textfile.zip HTTP/1.1'+#13#10;<br> //url1:=url1+'GET /textfile.zip HTTP/1.1'+#13#10;<br> url1:=url1+'GET /'+self.serfilename+' HTTP/1.1'+#13#10;<br> //url1:=url1+'HEAD /'+self.serfilename+' HTTP/1.1'+#13#10;<br> url1:=url1+'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'+#13#10;<br> //应该可以不要<br> //url1:=url1+'Accept-Language: zh-cn'+#13#10;<br> //应该可以不要<br> //url1:=url1+'Accept-Encoding: gzip, deflate'+#13#10;<br><br> //不使用缓存,我附加的<br> //与以前的服务器兼容<br> //url1:=url1+'Pragma: no-cache'+#13#10;<br> //新的<br> //url1:=url1+'Cache-Control: no-cache'+#13#10;<br><br> //不使用缓存,我附加的_end;<br><br> url1:=url1+'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)'+#13#10;<br> //接受数据的范围,可选<br> //url1:=url1+'RANGE: bytes=533200-'+#13#10;<br> url1:=url1+'RANGE: bytes='+inttostr(533263)+'-533263'+#13#10;<br> //下面这句必须要有<br> //url1:=url1+'Host: clq.51.net'+#13#10;<br> url1:=url1+'Host: '+self.serhost1+#13#10;<br> //应该可以不要<br> //url1:=url1+'Connection: Keep-Alive'+#13#10;<br> url1:=url1+#13#10;<br> ClientSocket1.Socket.SendText(url1);<br><br><br> //while ClientSocket1.Active=true do<br> begin<br> zeromemory(@buf1,sizeof(buf1));<br> rec1:=ClientSocket1.Socket.ReceiveBuf(buf1,sizeof(buf1));<br><br> real_reclen1:=real_reclen1+rec1;<br><br> memo1.Lines.Add(strpas(@buf1));<br><br> application.ProcessMessages;<br> //if self.stop1=true then break;<br> end;<br><br> ClientSocket1.Active:=false;<br><br> showmessage('ok');<br><br><br>end;<br><br>procedure TForm1.Button4Click(Sender: TObject);<br>begin<br> self.stop1:=true;<br>end;<br><br>end.