2016-09-13 40 views
1

對於一些實驗上偶爾錯用簡單的HTTP服務器代碼的工作here的Content-Length簡單的C#HTTP服務器

在我希望它成爲一些ANSI編碼的文本配置文件一例。我知道這段代碼有更多的問題,但目前我唯一關心的是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)

所以內容長度應該是29623.但產生的HTTP標頭是

Content-Length: 29617 

我從小提琴手保存的HTTP內容的主體和明顯的比較中的文件,也沒有注意到任何區別。然後,他們裝成BeyondCompare六角比較,有幾個問題的文件是這樣的:

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 

我懷疑問題是與編碼,但不能完全確定。只提供ANSI編碼文件,不支持Unicode。

我提出的文件通過修改與字節序列中的文件的部分正確地與右的Content-Length服務。在製造3份文件的這一變化:

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

回答

4

根據您粘貼字節,它看起來像有一對夫婦的東西去錯在這裏。首先,您的輸入文件(0D 0A)中的CRLF似乎正在轉換爲LF(0A)。其次,它看起來像字符編碼是變化的,要麼把文件讀入一個string時,或Write荷蘭國際集團串到HTTP客戶端。

的HTTP內容長度表示在流中的字節數,而string.length減給你在字符串中的字符數。除非你的文件是專門使用前128個ASCII字符(這就排除了非英文字符以及特殊的Windows-1252字符,如歐元符號),這是不可能的string.length減將字符串完全相等的長度,無論是UTF編碼-8或ISO-8859-1。

如果你把它發送到客戶端之前的字符串轉換爲byte[],你就可以得到「真正的」內容長度。但是,如果您沒有使用正確的編碼讀取文件,那麼您仍然會得到損壞的文本。 (無論您指定的編碼與否,轉換文件讀入的Unicode字符string時發生。)

我強烈建議在Content-Type標題中指定charset(例如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)); –