2011-01-17 14 views
1

これをどうやって始めたらよいかわかりません。私は、単純なテキストファイルをダウンロードしたチュートリアルのほかに、ファイルのダウンロードに関する知識がほとんどありません。ファイルから最新の変更を連続してダウンロードする

ダウンロードするファイルの種類を教えてください。私はローカルのデモを記録するゲームを持っています。このファイルは、いわゆるフレームを追加することで成長を続けています。 私たちが達成しようとしているのは、このファイルを完全にダウンロードしてダウンロードした後で、ファイル全体ではなく最新のファイルを取り出すことだけです。これにより、まだ作成中のリモートシステムでデモを再生することができます。

私たちはwgetを使用してこれを正常に実行しましたが、ダウンロードメカニズムの周りにユーザーフレンドリーなクライアントを作成したかったのです。だから、wgetは、ファイルが変更されたかどうかをチェックし、最後に追加されたバイトだけを取り出します。ファイルは約40KBpsになります。このようにして、リモートシステムへのストリームを簡単にセットアップできます。

ファイル全体を常にダウンロードすることはできません。オンラインファイルが変更されたかどうかを確認することができましたが、変更を検出したときにファイル全体をダウンロードしました。これらのファイルは最終的に最大15MBまで拡張することができます。このサイズのため、実際にはすぐにダウンロードしたり、ゲームの現在のフレームにスキップすることはできません。

ソースコード、チュートリアル、またはちょっとした説明があるダウンロードコードだけでも、どのように動作するのかは、プロジェクトに多大な影響を与えます。

ありがとうございます。

+0

どのようにファイルにアクセスしていますか? HTTP? Tcp/IPストリーム、その他?これはクライアント側のみにすることができますか、サーバー側を変更できますか? –

答えて

0

ファイルを取得するためにHTTP要求を使用していると仮定すると、次のように役立ちます。最後に変更された長さの値とコンテンツの長さの両方の値を利用し、ファイルの変更をポーリングします。ファイルに触れて更新しない場合、または何らかの理由でehaderが変更される可能性がある場合、これを変更することができます。これは変更を探す上では大した方法ではありません。しかし、これは正しい方向に動くはずです。

あなたが本当に動機を得たら、私がプログラムで使用するスレッドにポーリングコードを置き、 "FileUpdatedEventArgs"クラスを作成し、イベントを介して変更を戻すことができます。 - それとも自分でポーリングするだけでもいいかもしれません。このような方法で使用することができ;-)

public class SegmentedDownloader 
{ 
    #region Class Variables 

    /// <summary> 
    /// Date the file was last updated 
    /// Used to compare the header file for changes since 
    /// </summary> 
    protected DateTime LastModifiedSince = default(DateTime); 

    /// <summary> 
    /// Length of the file when it was last downlaoded 
    /// (this will be used to provide a content offset on next download) 
    /// </summary> 
    protected Int64 ContentLength = default(Int64); 

    /// <summary> 
    /// The file we're polling 
    /// </summary> 
    protected Uri FileLocation; 

    #endregion 

    #region Construct 

    /// <summary> 
    /// Create a new downloader pointing to the specific file location 
    /// </summary> 
    /// <param name="URL">URL of the file</param> 
    public SegmentedDownloader(String URL) 
     : this(new Uri(URL)) 
    { 
    } 

    public SegmentedDownloader(Uri URL) 
    { 
     this.FileLocation = URL; 
    } 

    #endregion 

    /// <summary> 
    /// Grab the latests details from the page 
    /// </summary> 
    /// <returns>Stream with the changes</returns> 
    public Stream GetLatest() 
    { 
     Stream result = null; 

     try 
     { 
      HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(this.FileLocation); 
      if (this.ContentLength > 0) 
       webRequest.AddRange(this.ContentLength); 
      webRequest.IfModifiedSince = this.LastModifiedSince; 

      HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); 

      Int64 contentLength = webResponse.ContentLength; 
      DateTime lastModifiedSince = Convert.ToDateTime(webResponse.Headers["Last-Modified"]); 
      if (contentLength > 0 || lastModifiedSince.CompareTo(this.LastModifiedSince) > 0) 
      { 
       result = webResponse.GetResponseStream(); 
       this.ContentLength += contentLength; 
       this.LastModifiedSince = lastModifiedSince; 
      } 
     } 
     //catch (System.Net.WebException wex) 
     //{ // 302 = unchanged 
     // Console.WriteLine("Unchanged"); 
     //} 
     catch (Exception) 
     { 
      result = null; 
     } 
     return result; 
    } 
} 

class Program 
{ 
    static TimeSpan updateInterval = TimeSpan.FromSeconds(5); 
    static Thread tWorker; 
    static ManualResetEvent tReset; 

    static void Main(string[] args) 
    { 
     tReset = new ManualResetEvent(false); 
     tWorker = new Thread(new ThreadStart(PollForUpdates)); 
     tWorker.Start(); 

     Console.Title = "Press ENTER to stop"; 
     Console.ReadLine(); 

     tReset.Set(); 
     tWorker.Join(); 
    } 

    static void PollForUpdates() 
    { 
     SegmentedDownloader segDL = new SegmentedDownloader("http://localhost/dataFile.txt"); 
     do 
     { 
      Stream fileData = segDL.GetLatest(); 
      if (fileData != null) 
      { 
       using (StreamReader fileReader = new StreamReader(fileData)) 
       { 
        if (fileReader.Peek() > 0) 
        { 
         do 
         { 
          Console.WriteLine(fileReader.ReadLine()); 
         } 
         while (!fileReader.EndOfStream); 
        } 
       } 
      } 
     } 
     while (!tReset.WaitOne(updateInterval)); 
    } 
} 
3

シンプルな実装

  • HEADリクエスト
  • を行い地元の長さと内容の長さを比較することにより、(ファイルの新しい部分を要求するコンテンツ長
  • 使用バイト範囲ゲット - だけを
  • )ダウンロードマネージャのような機能を再開することはあなたのローカルファイルに完了

それを追加します。

+0

私はこれがローカルファイルであるという印象を受けています( '私はローカルデモを記録したゲームがあります)。だから私はHTTPヘッダーが正しいアプローチだとは思わない。私はこれがWebファイルの解決策であるとは反対しませんが、これは*この問題の解決策ではありません。 –

+0

私は彼がダウンロードしてローカルの自分のゲームにストリームしたいファイルだと理解しています。だから私またはあなたが質問を逃した、私は私たちはOPの答えを待つと思う:) –

0

まず、ファイルとは思わないでください。あなたが扱っているようなものは、時間が経つにつれて改ざんパケットの流れです。ローカルマシン上のベースファイルが欠落しているか古い場合は、ベースを確立するためにいくつかの追加ダウンロードが必要ですが、一度使用すると、ほとんどの場合に使用されるコードは更新フレームを受信して​​います元のデータを追加または重ねることによって、それらをベースに追加することができます。

バージョン管理システムのように、この考える、または少なくともバージョン管理用語に慣れると同様の概念を使用して、あなたのソリューションにアプローチすると便利かもしれません。すべてのリビジョンには固有のシグニチャ(通常は実際のデータのハッシュまたはダイジェスト)があり、シグニチャに関連付けられた順序があります。クライアントが常にフレームを順番に取得するように要求できる場合(クライアントにフレーム150-199がまだない場合はフレーム200を持たないようにしてください)、クライアントのサーバーへの要求は単純に「持っていますxyz。私は最新の最新情報が必要ですか? "

あなたのデータ変更は、彼らが共有ドキュメント上で同時に動作する複数のクライアントの結果である場合は特に、急速に起こる場合には、一人の時間の署名を使用すると、おそらく信頼できるのに十分一意ではありません。拍子記号+コンテンツのデジタルハッシュはおそらく良いアイデアであり、それはほとんどのバージョン管理システムが何らかの方法で使うものだと私は信じています。

バージョン管理システムをコアの実装として使用し、独自のサーバーを作成する代わりにサーバーとクライアントを構築することも検討する価値があります。これは、ユーザーが以前のリビジョンに戻るか、現在のドキュメントを取得して他の誰にも見られないプライベートな変更(バージョン管理用語ではプライベートブランチ)を許可するというアプリケーションの要件がある場合に特に便利です。

0

私はここで質問された余分な質問を読んでいます: 私たちはHTTP経由でファイルにアクセスしています。それはウェブサーバーにプッシュされます。プッシュメカニズムは後で対処できるものです。今はプログラムを起動してローカルで変更を確認する醜いバッチファイルを使用していますが、これはユーザーにとっては不可視ですので、後で心配してください。

その他の2つの質問については、おおよその動作です。 ゲームサーバーに接続されたゲームはデモをローカルに記録します - >このデモはウェブスペースにアップロードされます - >このデモはデモを再生できるローカルユーザーにダウンロードする必要があります。

+0

私は解決策を投稿したので、いくつかのものがクリアされました。それが助けになるか、少なくともあなたが正しい場所にいるかどうかを確認してください。 –

関連する問題