我正在使用HTTP在C#中创建一个TCP连接到一些mp3流来分析请求。 当我打开连接时,我总是使用
关闭它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 :(得分:1)
您发送每行的内容以及每个\r
和\n
各自的Write
内容。这样,请求可能会分布在多个TCP数据包上,理论上这不是问题 - 因为TCP只是一个没有隐式消息边界的数据流。但是,一些实验表明,在这种情况下,这实际上是一个问题:如果一个人在一次写入中发送请求(这导致一个数据包)它将起作用,如果它分散在多个写入,就像在你的情况下,它将导致在400 Bad Request
。
我的猜测是,在Web服务器前面或服务器内部都有一些保护,它试图检测像Slowloris这样的DOS攻击,攻击者通过许多数据包传播HTTP请求。虽然您没有进行此类攻击,但您的代码导致的行为(请求分布在多个数据包上)可能会触发此DOS检测,然后提前拒绝该请求。
修复不是将请求头的每个部分立即写入套接字,而是收集内部缓冲区内的所有内容,然后发送此缓冲区,然后在一次写入套接字内。