このシステムの可能なアーキテクチャをスケッチします。これは不完全です。前半は詳細な疑似 C# コードの形式であり、後半は一連のヒントと提案であると考えてください。
これには 2 つのアプリケーションが必要になると思います。
- AC# WinForms クライアント。
- AC# サーバー側アプリケーション、おそらく Web サービス。
この回答ではセキュリティの問題には焦点を当てませんが、明らかに非常に重要です。おそらくSSLを使用して、より高いレベルでセキュリティを実装できると思います。Web サービスは IIS 内で実行され、何らかの形式のセキュリティを実装するには、主に構成の問題が必要です。
特に圧縮が必要ない場合は、サーバー側の部分は厳密には必要ありません。おそらく、 website.com /updaterで HTTP リクエストが行われたときに簡単に解析できるファイルのリストを返すようにサーバーを構成する方法があります。ただし、Web サービスを使用する方がより柔軟であり、おそらく実装がさらに簡単です。まず、この MSDN の記事 を参照してください。圧縮が必要な場合は、個々のファイルを透過的に圧縮するようにサーバーを構成できます。考えられるすべてのバリエーションをスケッチしてみます。
1 つの更新 ZIP ファイルの場合、基本的にアップデータ Web サービスは 2 つの異なる要求に応答できる必要があります。まず、サーバー ディレクトリwebsite.com/updaterに関連するすべてのゲーム ファイルのリストを、それらの最終書き込みタイムスタンプ ( GetUpdateInfo ) と共に返すことができます。メソッド)。クライアントは、このリストをローカル ファイルと比較します。一部のファイルはサーバー上にもう存在しない可能性があり (おそらくクライアントはローカル コピーを削除する必要があります)、一部はクライアント上に存在しない可能性があり (完全に新しいコンテンツです)、その他のファイルはクライアントとサーバーの両方に存在する可能性があります。その場合、クライアントは最終書き込み時刻をチェックして、更新されたバージョンが必要かどうかを判断する必要があります。クライアントは、ゲーム コンテンツ ディレクトリを基準にして、これらのファイルのパスのリストを作成します。ゲーム コンテンツ ディレクトリは、サーバーのwebsite.com/updaterディレクトリをミラーリングする必要があります。
次に、クライアントはこのリストをサーバーに送信します ( Web サービスのGetUpdateURL )。サーバーは更新を含む ZIP を作成し、その URL で応答します。
[ServiceContract]
public interface IUpdater
{
[OperationContract]
public FileModified[] GetUpdateInfo();
[OperationContract]
public string GetUpdateURL();
}
[DataContract]
public class FileModified
{
[DataMember]
public string Path;
[DataMember]
public DateTime Modified;
}
public class Updater : IUpdater
{
public FileModified[] GetUpdateInfo()
{
// Get the physical directory
string updateDir = HostingEnvironment.MapPath("website.com/updater");
IList<FileModified> updateInfo = new List<FileModified>();
foreach (string path in Directory.GetFiles(updateDir))
{
FileModified fm = new FileModified();
fm.Path = // You may need to adjust path so that it is local with respect to updateDir
fm.Modified = new FileInfo(path).LastWriteTime;
updateInfo.Add(fm);
}
return updateInfo.ToArray();
}
[OperationContract]
public string GetUpdateURL(string[] files)
{
// You could use System.IO.Compression.ZipArchive and its
// method CreateEntryFromFile. You create a ZipArchive by
// calling ZipFile.Open. The name of the file should probably
// be unique for the update session, to avoid that two concurrent
// updates from different clients will conflict. You could also
// cache the ZIP packages you create, in a way that if a future
// update requires the same exact file you would return the same
// ZIP.
// You have to return the URL of the ZIP, not its local path on the
// server. There may be several ways to do this, and they tend to
// depend on the server configuration.
return urlOfTheUpdate;
}
}
クライアントは、 HttpWebRequestおよびHttpWebResponseオブジェクトを使用して ZIP ファイルをダウンロードします。プログレス バーを更新するには (この設定ではプログレス バーが 1 つしかありません。質問に対する私のコメントを確認してください)、BackgroundWorkerを作成する必要があります。この記事とこの別の記事では、関連する側面について説明します (残念ながら、この例は VB.NET で書かれていますが、C# の場合と非常によく似ています)。プログレス バーを進めるには、受信したバイト数を追跡する必要があります。
int nTotalRead = 0;
HttpWebRequest theRequest;
HttpWebResponse theResponse;
...
byte[] readBytes = new byte[1024];
int bytesRead = theResponse.GetResponseStream.Read(readBytes, 0, 4096);
nTotalRead += bytesread;
int percent = (int)((nTotalRead * 100.0) / length);
ファイルを受け取ったら、System.IO.Compression.ZipArchive.ExtractToDirectoryを使用してゲームを更新できます。
ファイルを .NET で明示的に圧縮したくない場合でも、Web サービスの最初の方法を使用して更新されたファイルのリストを取得し、HttpWebRequest/HttpWebResponseペアを使用して必要なファイルをクライアントにコピーできます。各。このようにして、実際には 2 つのプログレス バーを表示できます。ファイルをカウントするものは、次のようなパーセンテージに単純に設定されます。
int filesPercent = (int)((nCurrentFile * 100.0) / nTotalFiles);
リストを取得する別の方法がある場合は、Web サービスも必要ありません。
ファイルを個別に圧縮したいが、この機能をサーバーによって自動的に実装できない場合は、次のインターフェイスを使用して Web サービスを定義する必要があります。
[ServiceContract]
public interface IUpdater
{
[OperationContract]
public FileModified[] GetUpdateInfo();
[OperationContract]
public string CompressFileAndGetURL(string path);
}
サーバーに特定のファイルを圧縮し、圧縮された単一ファイルのアーカイブの URL を返すように要求できます。
編集 - 重要
特に更新頻度が非常に高い場合は、タイム ゾーンに特に注意する必要があります。
編集 - 代替案
ここでの主な問題の 1 つは、現在のリリースのファイルのリストをサーバーから取得することです。このファイルには、各ファイルの最終書き込み時刻が含まれている必要があります。Apache のようなサーバーは、そのようなリストを無料で提供できますが、通常は人間が使用することを目的としていますが、それでもプログラムで簡単に解析できます。そのリストをさらにマシンフレンドリーな方法でフォーマットするには、何らかのスクリプト/拡張機能が必要だと確信しています。
そのリストを取得する別の方法があります。サーバー上に、すべてのゲーム コンテンツファイルの最終書き込み時刻、またはプログレッシブ リリース番号を格納するテキスト ファイルを配置することもできます。日付ではなくリリース番号を比較して、必要なファイルを確認します。これにより、タイムゾーンの問題から身を守ることができます. ただし、この場合、ファイルにはリリース番号のようなものはなく、名前と一連の日付しかないため、このリストのローカル コピーを維持する必要があります。