2016-07-12 13 views
2

httpwebrequestsを使用してカスタムWebサーバーから小さなバイナリファイル(20-25 KB)をダウンロードするアプリケーションを構築しようとしています。この後C# - httpWebRequestストリームのサイズに制限はありますか?

Stream UpdateRequest = context.Request.InputStream; 
byte[] UpdateContent = new byte[context.Request.ContentLength64]; 
UpdateRequest.Read(UpdateContent, 0, UpdateContent.Length); 
String remoteVersion = ""; 
for (int i = 0;i < UpdateContent.Length;i++) { //check if update is necessary 
    remoteVersion += (char)UpdateContent[i]; 
} 

byte[] UpdateRequestResponse; 

if (remoteVersion == remotePluginVersion) { 
    UpdateRequestResponse = new byte[1]; 
    UpdateRequestResponse[0] = 0; //respond with a single byte set to 0 if no update is required 
} else { 
    FileInfo info = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), "remote logs", "PointAwarder.dll")); 
    UpdateRequestResponse = File.ReadAllBytes(Path.Combine(Directory.GetCurrentDirectory(), "remote logs", "PointAwarder.dll")); 
    //respond with the updated file otherwise 
} 

//this byte is past the threshold and will not be the same in the version the client recieves 
Console.WriteLine("5000th byte: " + UpdateRequestResponse[5000]); 

//send the response 
context.Response.ContentLength64 = UpdateRequestResponse.Length; 
context.Response.OutputStream.Write(UpdateRequestResponse, 0, UpdateRequestResponse.Length); 
context.Response.Close(); 

配列UpdateRequestResponseは、ファイル全体が含まれており、クライアントに送信されました:

これは、サーバー側のコードです。

クライアントは、このコードを実行します。クライアント上の

//create the request 
WebRequest request = WebRequest.Create(url + "pluginUpdate"); 
request.Method = "POST"; 
//create a byte array of the current version 
byte[] requestContentTemp = version.ToByteArray(); 
int count = 0; 
for (int i = 0; i < requestContentTemp.Length; i++) { 
    if (requestContentTemp[i] != 0) { 
     count++; 
    } 
} 
byte[] requestContent = new byte[count]; 
for (int i = 0, j = 0; i < requestContentTemp.Length; i++) { 
    if (requestContentTemp[i] != 0) { 
     requestContent[j] = requestContentTemp[i]; 
     j++; 
    } 
} 

//send the current version 
request.ContentLength = requestContent.Length; 
Stream dataStream = request.GetRequestStream(); 
dataStream.Write(requestContent, 0, requestContent.Length); 
dataStream.Close(); 

//get and read the response 
WebResponse response = request.GetResponse(); 
Stream responseStream = response.GetResponseStream(); 
byte[] responseBytes = new byte[response.ContentLength]; 
responseStream.Read(responseBytes, 0, (int)response.ContentLength); 
responseStream.Close(); 
response.Close(); 

//if the response containd a single 0 we are up-to-date, otherwise write the content of the response to file 
if (responseBytes[0] != 0 || response.ContentLength > 1) { 
    BinaryWriter writer = new BinaryWriter(File.Open(Path.Combine(Directory.GetCurrentDirectory(), "ServerPlugins", "PointAwarder.dll"), FileMode.Create)); 
    writer.BaseStream.Write(responseBytes, 0, responseBytes.Length); 
    writer.Close(); 
    TShockAPI.Commands.HandleCommand(TSPlayer.Server, "/reload"); 
} 

バイト配列responseBytesは、サーバー上のアレイのUpdateRequestResponseと同一である必要がありますが、そうではありません。その後の約4000バイトの後は、それ以降のすべてのバイトが0に設定されます(responseBytes [3985]は最後の非ゼロバイトです)。

httpWebRequestにサイズ制限があるため、これは起こりますか?私はそれを引き起こす可能性のあるコード内のバグを見ることができず、同じコードは短いデータシーケンス(100バイト未満)を渡すだけで済む他のインスタンスでも機能します。

MSDNページにはこのようなサイズ制限はありません。

答えて

2

人為的な制限はありません。これは、あなたがしようとしていることの性質の副産物です。私は次の行を感じたことは犯罪者である:

responseStream.Read(responseBytes, 0, (int)response.ContentLength); 

なぜなら、彼らは避難所」私は、それが配列の内容のすべてを読んでいない、(TCPストリームで)過去にこの問題を持っていましたすべてがまだワイヤーで送られてきました。これが私が代わりに試みるものです。

for (int i = 0; i < response.ContentLength; i++) 
{ 
    responseBytes[i] = responseStream.ReadByte(); 
} 

このようにして、ストリームの最後まで必ず読み込みます。

EDIT

USRのBinaryReaderベースのソリューションは、はるかに効率的です。

BinaryReader binReader = new BinaryReader(responseStream); 
const int bufferSize = 4096; 
byte[] responseBytes; 
using (MemoryStream ms = new MemoryStream()) 
{ 
    byte[] buffer = new byte[bufferSize]; 
    int count; 
    while ((count = binReader.Read(buffer, 0, buffer.Length)) != 0) 
     ms.Write(buffer, 0, count); 
    responseBytes = ms.ToArray(); 
} 
+0

それはそれを修正したようです!どうもありがとうございました。私は、すべてのデータが完全に送信されるまで実行が中断されたと考えました。これが私の最初の質問なので、次回に改善することができるものはありますか? – Annonymus

+0

これは難しい問題ですが、私は実際に(ローカル!)うまく動作していたコードをプロダクションにプッシュし、この問題を考慮しなかったためにライブテストで失敗し始めました。質問は非常によく書かれていたので、私は残念なことに、そこに助言がありません! –

+0

それは悪夢のように聞こえる!私の場合は、ローカルでは全くテストすることができません。ライブサーバー上でアプリケーションの2番目のインスタンスを作成する必要があります(ポート/パイプ名の変更など)。私の質問がうまく書かれたのは残念だと思いますか?それは私に奇妙な印象を与えます...しかし、賛辞をありがとう。 – Annonymus

2

あなたが要求するようReadは、できるだけ多くのバイトを読んでいると仮定されています。ここでは、関連するソリューションです。しかし、要求された数は上限に過ぎません。あなたは小さな塊を読むことを許さなければなりません。

var bytes = new BinaryReader(myStream).ReadBytes(count);を使用すると、正確な数値を読み取ることができます。 ReadByteにはあまりにも頻繁に呼び出さないでください。なぜなら、これはCPUを大量に消費するためです。

最も適切な解決策は、かなり手動のHttpWebRequestから離れて、HttpClientまたはWebClientを使用することです。これはすべて自動化され、byte[]に戻ります。

+0

よろしくお願いします。私はこれを反映するために私の答えを変更しました。残念ながら、['ReadBytes()'呼び出しは32ビットシステム上で 'OutOfMemoryException'をスローします。](http://stackoverflow.com/questions/8613187/an-elegant-way-to-consume-all-bytes-of- a-binaryreader)を返します。あなたの方法と回避策を使って答えを更新しました。 –

+0

とにかく長い配列を作成する方法はありません。 MemStreamとbyte []はどちらもできません。 – usr

関連する問題