由于客戶端有的文件經常更新(遠程的,不是局域網),
所以想寫個自動更新的 程序。
看網上的 方法資料,知道些方法,但不知道具體怎么寫。要不要服務器端寫個程序,客戶端也要寫個程序。
怎么做,用到什么控件,有寫過的大俠能否給個說明和源碼,我參考參考
謝謝!!!急需!!!

解决方案 »

  1.   

    下载更新包有通过Http或者FTP下载;过程一般是这样的:在你的Http或FTP服务器上编辑一个文件用来保存更新的内容,比如叫Update.ini。这个文件里有你软件的更新的版本信息等。当你客户端启动的时候就调更新程序后台运行,更新程序从Http服务器下载pdate.ini文件并解析,判断要更新的内容,然后把这些要更新的文件下载到一个临时文件夹下,接着给客户端程序发一个退出消息,客端程序收到这个消息后退出程序,更新程序把临时文件夹下覆盖到客户端的目录下,然后再重新启动客户端,更新程序退出。这样就完成更新了,我就是这样做的
      

  2.   

    2楼说的不错,基本就是这样。
    代码很简单,曾经写过一个用ftp或idhttp都可以。
    1.在主程序中,每次取服务器上的txt或ini版本文件与当前程序的对比。
    2.发现不一致,启动自动更新的程序,开始下载,名称可以与当前不一样。
    3.下载完毕后,关掉当前主程序,将刚下载的命名成当前的程序
    4.启动新程序,退出更新程序。
      

  3.   

    急需源碼參考。大俠們救命呀。發個參考到[email protected]好么???
    不勝感激!!!
    是不是  服務器端一個程序  客戶端一個程序????
      

  4.   

    好像找到參考的資料了  
    不過大家有的話 也可以發到我說的郵箱 
    便于比較還有一個問題:
    我用過fastnet中的nmudp控件,但是只是在局域網中使用,
    想知道在廣域網中 可以不可以用
    是不是 跟局域網中一樣,只要把那個remotehost的屬性賦值為遠程的ip地址就可以了?
    在局域網中使用的時候,我是用局域網電腦的ip地址如192.168.1.x
      

  5.   


    function getfiledate(const filename2: string; var d: TDateTime): Boolean;
    var
      DosFileTime: integer;
    begin
      result := false;
      DosFileTime := FileAge(filename2);
      if DosFileTime <> -1 then //返回-1表示文件不存在
      begin
        d := FileDateToDateTime(DosFileTime);
        result := true;
      end;
    end;function socket_rec_line1(socket1: TCustomWinSocket; timeout1: integer; crlf1: string = #13#10): string;
    var
      buf1: Tbuf_char;
      r1: integer;
      ts1: TStringStream; //保存所有的数据
      FSocketStream: TWinSocketStream;
    begin
      ts1 := TStringStream.Create('');
      FSocketStream := TWinSocketStream.create(Socket1, timeout1);
      //while true do//下面的一句更安全,不过对本程序好象没起作用
      while (socket1.Connected = true) do
      begin
        //确定是否可以接收数据
        //只能确定接收的超时,可见WaitForData的源码
        if not FSocketStream.WaitForData(timeout1) then break; //continue;
        //这一句是一定要有的,以免返回的数据不正确
        zeromemory(@buf1, sizeof(buf1));
        r1 := FsocketStream.Read(buf1, 1); //每次只读一个字符,以免读入了命令外的数据
        //读不出数据时也要跳出,要不会死循环
        if r1 = 0 then break; //test
        //用FsocketStream.Read能设置超时
        //r1:=socket1.ReceiveBuf(buf1,sizeof(buf1));
        ts1.Write(buf1, r1);
        //读到回车换行符了
        if pos(crlf1, ts1.DataString) <> 0 then
        begin
          break;
        end;
      end;
      result := ts1.DataString;
      //没有读到回车换行符,就表示有超时错,这时返回空字符串
      if pos(crlf1, result) = 0 then
      begin
        result := '';
      end;
      ts1.Free;
      FSocketStream.Free;
    end;function get_host1(in1: string): string;
    begin
      in1 := trim(in1);
      if pos('http://', lowercase(in1)) = 1 then
      begin
        in1 := copy(in1, length('http://') + 1, length(in1));
      end;
      if pos('/', in1) <> 0 then
      begin
        in1 := copy(in1, 0, pos('/', in1) - 1);
      end;
      if pos(':', in1) <> 0 then
      begin
        in1 := copy(in1,0 ,pos(':', in1) -1);
      end;
      result := in1;
    end;function get_file1(in1: string): string;
    begin
      in1 := trim(in1);
      if pos('http://', lowercase(in1)) = 1 then
      begin
        in1 := copy(in1, length('http://') + 1, length(in1));
      end;
      if pos('/', in1) <> 0 then
      begin
        in1 := copy(in1, pos('/', in1) + 1, length(in1));
      end;
      result := in1;
    end;function get_port(in1: string): string;
    begin
      in1 := trim(in1);
      if pos('http://', lowercase(in1)) = 1 then
      begin
        in1 := copy(in1, length('http://') + 1, length(in1));
      end;
      if pos('/', in1) <> 0 then
      begin
        in1 := copy(in1, 0, pos('/', in1) - 1);
      end;
      if pos(':', in1) <> 0 then
      begin
        in1 := copy(in1, pos(':', in1) + 1, length(in1));
      end;
      result := in1;
    end;function Download(var host1, file1: string): Boolean;
    var
      url1: string;
      buf1: Tbuf_byte;
      rec1: longint;
      f1: file;
      cmd1: string; //这一行的内容
      reclen1, real_reclen1: longint; //服务器返回的长度;实际已经收到的长度
      value1: string; //标志们的值
      total_len1: longint; //数据总长
    begin
       reclen1:=0;
       total_len1:=0;
      try
        //self.filename1:='c:\temp1.dat';
        assignfile(f1, file1);
        Form_Update.can_rec1 := false;
        Form_update.stop1 := false;
        if FileExists(file1) = true then
        begin
          reset(f1, 1);
          pos1 :=0;
        end
        else
        begin
          rewrite(f1, 1);
          pos1 := 0;
        end;
        seek(f1, pos1);
        Form_Update.ClientSocket1.Active := false;
        Form_Update.ClientSocket1.Host := get_host1(host1);
        Form_Update.ClientSocket1.Port :=StrToIntDef(get_port(host1),80);
        url1 := '';
        Form_Update.serfilename := get_file1(host1);
        Form_Update.serhost1 := get_host1(host1);
        //取得文件长度以确定什么时候结束接收[通过"head"请求得到]
        Form_Update.ClientSocket1.Active := false;
        Form_Update.ClientSocket1.Active := true;
        url1 := '';
        url1 := url1 + 'HEAD /' + Form_Update.serfilename + ' HTTP/1.1' + #13#10;
        //不使用缓存,我附加的
        //与以前的服务器兼容
        url1 := url1 + 'Pragma: no-cache' + #13#10;
        //新的
        url1 := url1 + 'Cache-Control: no-cache' + #13#10;
        //不使用缓存,我附加的_end;
        url1 := url1 + 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)' + #13#10;
        //下面这句必须要有
        //url1:=url1+'Host: clq.51.net'+#13#10;
        url1 := url1 + 'Host: ' + Form_Update.serhost1 + #13#10;
        url1 := url1 + #13#10;
        Form_Update.ClientSocket1.Socket.SendText(url1);
        while Form_Update.ClientSocket1.Active = true do
        begin
          if Form_Update.stop1 = true then break;
          cmd1 := socket_rec_line1(Form_Update.ClientSocket1.Socket, 60 * 1000);
          //计算文件的长度
          if pos(lowercase('Content-Length: '), lowercase(cmd1)) = 1 then
          begin
            value1 := copy(cmd1, length('Content-Length: ') + 1, length(cmd1));
            total_len1 := strtoint(trim(value1));
          end;
          //计算文件的长度_end;
          if cmd1 = #13#10 then break;
        end;
        //取得文件长度以确定什么时候结束接收_end;
        //发送get请求,以得到实际的文件数据
        Form_Update.clientsocket1.Active := false;
        Form_Update.clientsocket1.Active := true;
        url1 := '';
        //url1:=url1+'GET http://clq.51.net/textfile.zip HTTP/1.1'+#13#10;
        //url1:=url1+'GET /textfile.zip HTTP/1.1'+#13#10;
        url1 := url1 + 'GET /' + Form_Update.serfilename + ' HTTP/1.1' + #13#10;
        url1 := url1 + 'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*' + #13#10;
        //应该可以不要url1:=url1+'Accept-Language: zh-cn'+#13#10;
        //应该可以不要url1:=url1+'Accept-Encoding: gzip, deflate'+#13#10;
        //不使用缓存,我附加的
        //与以前的服务器兼容
        //url1:=url1+'Pragma: no-cache'+#13#10;
        //新的
        //url1:=url1+'Cache-Control: no-cache'+#13#10;
        //不使用缓存,我附加的_end;
        url1 := url1 + 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)' + #13#10;
        //接受数据的范围,可选
        //url1:=url1+'RANGE: bytes=533200-'+#13#10;
        url1 := url1 + 'RANGE: bytes=' + inttostr(pos1) + '-' + #13#10;
        //下面这句必须要有
        //url1:=url1+'Host: clq.51.net'+#13#10;
        url1 := url1 + 'Host: ' + Form_Update.serhost1 + #13#10;
        //应该可以不要
        //url1:=url1+'Connection: Keep-Alive'+#13#10;
        url1 := url1 + #13#10;
        Form_Update.ClientSocket1.Socket.SendText(url1);
        while Form_Update.ClientSocket1.Active = true do
        begin
          if Form_Update.stop1 = true then break;
          cmd1 := socket_rec_line1(Form_Update.ClientSocket1.Socket, 60 * 1000);
          //是否可接收
          if pos(lowercase('Content-Range:'), lowercase(cmd1)) = 1 then
          begin
            Form_Update.can_rec1 := true;
          end;
          //是否可接收_end;
          //计算要接收的长度
          if pos(lowercase('Content-Length: '), lowercase(cmd1)) = 1 then
          begin
            value1 := copy(cmd1, length('Content-Length: ') + 1, length(cmd1));
            reclen1 := strtoint(trim(value1));
          end;
          //计算要接收的长度_end;
          //头信息收完了
          if cmd1 = #13#10 then break;
        end;
        real_reclen1 := 0;
        while Form_Update.ClientSocket1.Active = true do
        begin
          if Form_Update.stop1 = true then break;
          //不能接收则退出
          if Form_Update.can_rec1 = false then break;
          //如果文件当前的长度大于服务器标识的长度,则是出错了,不要写入文件中
          if filesize(f1) >= total_len1 then
          begin
            //showmessage('文件已经下载完毕了!');
            result := true;
            Form_Update.Memo1.Lines.Add(file1 + '文件下载完成' + #13#10);
            break;
          end;
          zeromemory(@buf1, sizeof(buf1));
          rec1 := Form_Update.ClientSocket1.Socket.ReceiveBuf(buf1, sizeof(buf1));
          //如果实际收到的长度大于服务器标识的长度,则是出错了,不要写入文件中
          if real_reclen1 >= reclen1 then
          begin
            //showmessage('文件已经下载完毕了!');
            result := true;
            Form_Update.Memo1.Lines.Add(Form_update.serfilename + '实际收到文件长度大于服务器标识长度,跳过下载' + #13#10);
            break;
          end;
          //如果当前的长度大于服务器标识的长度,则是出错了,不要写入文件中
          if pos1 = reclen1 then
          begin
            //showmessage('文件已经下载完毕了!');
            result := true;
            Form_Update.Memo1.Lines.Add(Form_update.serfilename + '当前长度大于服务器标识长度,跳过下载' + #13#10);
            break;
          end;
          blockwrite(f1, buf1, rec1);
          real_reclen1 := real_reclen1 + rec1;      //显示下载进度
          Form_Update.Label4.Caption := '下载数据量:共 ' + FormatFloat('#,##', reclen1) + ' 字节,已下载 ' + FormatFloat('#,##', real_reclen1) + ' 字节';
          Form_Update.Gauge_process.MaxValue := reclen1;
          Form_Update.Gauge_process.Progress := real_reclen1;
         // Form_update.Notebook_step.Refresh;
          application.ProcessMessages;
        end;
        closefile(f1);
        //发送get请求,以得到实际的文件数据_end;
        Form_Update.ClientSocket1.Active := false;
      except
        closefile(f1);
        //showmessage('连接失败...');
        result := false;
      end;
    end;
      

  6.   

    可以参考这个,做得比较完整了.
    http://www.2ccc.com/article.asp?articleid=5037
      

  7.   

    俺用UDP,自己制定一些协议,考虑到对网络传输故障的容错处理.
    这个问题的核心,就是文件传输.
      

  8.   

    可以参考这个,做得比较完整了.
    http://www.2ccc.com/article.asp?articleid=5037俺用UDP,自己制定一些协议,考虑到对网络传输故障的容错处理.
    这个问题的核心,就是文件传输.