2017-10-08 9 views
0

HTTPを使用してリクエストを分析するために、C#でいくつかのmp3ストリームにTCP接続を作成しています。 は、私は、接続を開くと、私はいつもほとんどの場合、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

あなたは、独自のWriteで、各行の内容及び各\r\nそれぞれを送ります。このようにして、要求は理論的には問題ではない複数のTCPパケットに広がる可能性があります。なぜなら、TCPは暗黙的なメッセージ境界のないデータストリームに過ぎないからです。しかし、いくつかの実験では、実際にこの問題が発生していることが示されています。単一の書き込み(1つのパケットになります)内で要求を送信すると、 400 Bad Requestにあります。

私の推測によれば、ウェブサーバーの前または攻撃者が多くのパケットを介して多くの遅延をかけてHTTPリクエストを広げるSlowlorisのようなDOS攻撃を検出しようとするサーバーの内部に何らかの保護があります。このような攻撃はしませんが、コード(複数のパケットにまたがる要求)によって引き起こされる動作によって、このDOS検出がトリガーされ、要求が早期に拒否される可能性があります。

解決方法は、要求ヘッダーの各部分をソケットにただちに書き込むのではなく、内部バッファー内のすべてを収集し、このバッファーをソケットに1回書き込むことで送信します。

+0

これは完璧な答えでした!私はすべてのヘッダーをStringBuilderに追加し、すべてをすぐに書きました。それはとてもうまくいった。ありがとうございました!! – Basilf

関連する問題