2017-10-08 43 views
0

我正在用C#創建一個TCP連接到一些使用HTTP分析請求的mp3流。 當我打開連接,我總是用TCPClient大部分時間返回400

tcpClient.GetStream().Close(); 
tcpClient.Close(); 

我還試圖用其關閉:

client.Client.Disconnect(false); 

如果我再次運行我的應用程序,並重新連接,我收到400(錯誤請求)和連接關閉響應標題,即使我看到使用「netstat」,連接不再存在。 這是我到目前爲止的代碼:

string headers = new string [] { 
        "GET /stream HTTP/1.0", 
        "Host: sci.streamingmurah.com:8032", 
        "Connection: keep-alive", 
        "Accept-Encoding: identity;q=1, *;q=0", 
        "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36", 
        "Accept: */*", 
        "Referer: 82.XX.XX.XX", 
        "Accept-Language: en-US,en;q=0.8,he;q=0.6" 
      }; 
try 
{ 
    using (TcpClient client = new TcpClient()) 
    { 
     client.SendTimeout = 5000; 
     client.ReceiveTimeout = 5000; 
     client.Connect(host, port); 
     using (NetworkStream ns = client.GetStream()) 
     { 

      foreach (string requestHeader in headers) 
      { 
       Debug.WriteLine("Request Header: " + requestHeader); 

       byte[] headerBytes = Encoding.ASCII.GetBytes(requestHeader); 
       ns.Write(headerBytes, 0, headerBytes.Length); 
       ns.WriteByte(13); 
       ns.WriteByte(10); 
      } 

      ns.WriteByte(13); 
      ns.WriteByte(10); 

      List<string> responseHeaders = new List<string>(); 

      string responseHeader; 
      while (Utils.ReadLine(ns, Encoding.ASCII, out responseHeader) && responseHeader.Length > 0) 
      { 
       responseHeaders.Add(responseHeader); 
      } 
      //Response headers contains 
      if (responseHeaders.Count == 0) 
      { 
       traceInfo.AddLine(TraceInfo.EntryKind.Alert, "Response is empty"); 
       client.GetStream().Close(); 
       client.Close(); 
       //client.Client.Disconnect(false); 
       return null; 
      } 

      Playable pl = HandleResponse(responseHeaders.ToArray(), ns); 
      client.GetStream().Close(); 
      client.Close(); 
      return pl; 
     } 
    } 
} 
catch (Exception e) 
{ 
    traceInfo.AddLine(TraceInfo.EntryKind.Alert, String.Format("Exception: {0}", e.Message)); 
} 

return null; 

當然 - 如果我運行在Chrome流,它始終工作。所以我所做的一定是錯的。 有什麼想法?

感謝

+0

也許是因爲缺少Content-Length。 (你爲什麼不簡單地使用WebClient或HttpClient) –

+1

@ L.B:這是一個GET請求。它沒有內容,因此沒有使用Content-Length頭(瀏覽器也不這樣做)。 –

回答

1

您發送的每一行的內容和各\r\n在各自Write。這樣,請求可能分散在多個TCP數據包上,這在理論上不是問題 - 因爲TCP只是一個沒有隱含消息邊界的數據流。但是,一些實驗表明,在這種情況下,這實際上是一個問題:如果在單個寫入內發送請求(這會導致一個包),它將起作用,如果它分散在多個寫入上,就像在你的情況下一樣在400 Bad Request

我的猜測是在網絡服務器前面或服務器內部有一些保護措施,它們試圖檢測DOS攻擊,如Slowloris,攻擊者通過很多數據包將HTTP請求分散到很多數據包之間。儘管您不會執行此類攻擊,但您的代碼(請求分佈在多個數據包中)導致的行爲可能會觸發此DOS檢測,然後該檢測會盡早拒絕該請求。

修復將不會立即寫入套接字的每個部分的請求頭,而是收集一些內部緩衝區內的一切,然後發送這個緩衝區,然後在一次寫入套接字。

+0

這是一個完美的答案!我將所有頭文件添加到一個StringBuilder中,然後立即寫入所有內容。它工作得很好。謝謝!! – Basilf