2016-09-13 20 views
1

は、私はそれはいくつかのANSIエンコードされたテキストのコンフィギュレーションファイルを提供したかった一例では単純なHTTP ServerコードhereのContent-Length時折間違ったシンプルなC#のHTTP Server上

で働いていました。私は、このコードでもっと問題があることを認識していますが、私が現在気にしているのは、Content-Lengthが間違っている唯一のものですが、特定のテキストファイルのみです。

例コード:

出力ストリームの初期化:

outputStream = new StreamWriter(new BufferedStream(socket.GetStream())); 

HTTP GETの取り扱い:私はコンテンツの長さでテストした中で最もファイルについては

public override void handleGETRequest(HttpProcessor p) 
{ 

    if (p.http_url.EndsWith(".pac")) 
    { 
     string filename = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), p.http_url.Substring(1)); 
     Console.WriteLine(string.Format("HTTP request for : {0}", filename)); 
     if (File.Exists(filename)) 
     { 
      FileInfo fi = new FileInfo(filename); 
      DateTime lastWrite = fi.LastWriteTime; 

      Stream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 
      StreamReader sr = new StreamReader(fs); 
      string result = sr.ReadToEnd().Trim(); 
      Console.WriteLine(fi.Length); 
      Console.WriteLine(result.Length); 
      p.writeSuccess("application/x-javascript-config",result.Length,lastWrite); 
      p.outputStream.Write(result); 
      // fs.CopyTo(p.outputStream.BaseStream); 
      p.outputStream.BaseStream.Flush(); 
      fs.Close(); 
     } 
     else 
     { 
      Console.WriteLine("404 - FILE not found!"); 
      p.writeFailure(); 
     } 
    } 

} 

    public void writeSuccess(string content_type,long length,DateTime lastModified) { 
      outputStream.Write("HTTP/1.0 200 OK\r\n");    
      outputStream.Write("Content-Type: " + content_type + "\r\n"); 
      outputStream.Write("Last-Modified: {0}\r\n", lastModified.ToUniversalTime().ToString("r")); 
      outputStream.Write("Accept-Range: bytes\r\n"); 
      outputStream.Write("Server: FlakyHTTPServer/1.3\r\n"); 
      outputStream.Write("Date: {0}\r\n", DateTime.Now.ToUniversalTime().ToString("r")); 
      outputStream.Write(string.Format("Content-Length: {0}\r\n\r\n", length)); 
       } 

は正しいです。しかし、HTTPデバッグツールFiddlerでテストする場合、プロトコル違反がContent-Lengthで報告されることがあります。例えば、シオマネキについて

は言う:

要求数:送信1 バイト:303(ヘッダ:303;本体:0)を受信 バイト:29847を(ヘッダー:224;本体:29623)

だから私はフィドラーからHTTPコンテンツの体を保存し、目に見えてファイルを比較して、任意の違いに気付くことができなかったのContent-Lengthは29623.でなければなりません。しかし生成されたHTTPヘッダは

Content-Length: 29617 

です。

Original File: 2D 2D 96  20 2A 2F 
HTTP Content : 2D 2D EF BF BD 20 2A 2F 

Original File: 27 3B 0D 0A 09 7D 0D 0A 0D 0A 09 
HTTP Content : 27 3B 0A 09 7D 0A 0A 09 

私は問題がエンコーディングに関連しているが、正確に確認されていません疑う:次に、このようなファイルにはいくつかの問題があり、比較BeyondCompareヘックスにそれらをロード。 ANSIでエンコードされたファイルのみを提供し、Unicodeは提供しません。

ファイルの一部をバイトシーケンスで修正して、正しいContent-Lengthでファイルを正しく提供しました。ファイルの3部では、この変更を行った。ここで間違って行くカップルの事があるようにあなたが貼り付けられたバイトに基づいて

2D 2D 96 (--–) to 2D 2D 2D (---) 

答えて

4

、それが見えます。まず、入力ファイル(0D 0A)のCRLFがLF(0A)に変換されているようです。次に、ファイルをstring、またはWriteに読み込んだときに文字エンコーディングが変更されているように見えます。

HTTP Content-Lengthはストリーム内のバイト数を表しますが、string.Lengthは文字列内の文字数を示します。あなたのファイルが排他的に最初の128文字のASCII文字(英語以外の文字やユーロ記号のような特殊なウィンドウ-1252文字を排除する)を使用しない限り、string.LengthはどちらのUTFでもエンコードされた文字列の長さと正確に等しくはありません-8またはISO-8859-1。

文字列をbyte[]に変換してからクライアントに送信すると、「true」のContent-Lengthを取得できます。しかし、適切なエンコーディングを使用してファイルを読み取らなかった場合でも、文字化けしたテキストが残ってしまいます。 (エンコードを指定するかどうかに関係なく、ファイルをUnicode文字のstringに読み込むと変換が行われます。)

Content-Typeヘッダーに文字セットを指定することを強くおすすめします(例:application/x-javascript-config;charset=utf-8)。文字列をバイト[]に変換する際に使用するのと同じ文字エンコーディングであれば、文字セットがutf-8、utf-16、iso-8859-1、windows-1251などであるかどうかは関係ありません。

+0

バイト配列をクライアントに送信したいのですが、何らかの理由でoutputstream.BaseStream.Writeを使用した場合、コンテンツがクライアントに届きません。つまり、コンテンツの最後に半分のヘッダーがあります。始まり。しかし、私はASCIIコード化されたファイルを提供しています(今のところ)この固定の問題にコードを変更しています:byte [] data = File.ReadAllBytes(filename); p.writeSuccess( "application/x-javascript-config"、data.Length、lastWrite); p.outputStream.Write(System.Text.Encoding.ASCII.GetString(data)); –

関連する問題