2017-10-08 106 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