我正在为我的 Web 客户端使用 Socket
类。我无法使用 HttpWebRequest
,因为它不支持 socks 代理。所以我必须自己解析 header 并处理分块编码。对我来说最困难的事情是确定内容的长度,所以我必须逐字节阅读。首先,我必须使用 ReadByte()
找到最后一个 header (“\r\n\r\n”组合),然后检查正文是否具有传输编码。如果是这样,我必须读取 block 的大小等:
public void ParseHeaders(Stream stream)
{
while (true)
{
var lineBuffer = new List<byte>();
while (true)
{
int b = stream.ReadByte();
if (b == -1) return;
if (b == 10) break;
if (b != 13) lineBuffer.Add((byte)b);
}
string line = Encoding.ASCII.GetString(lineBuffer.ToArray());
if (line.Length == 0) break;
int pos = line.IndexOf(": ");
if (pos == -1) throw new VkException("Incorrect header format");
string key = line.Substring(0, pos);
string value = line.Substring(pos + 2);
Headers[key] = value;
}
}
但是这种方法的性能很差。你能建议更好的解决方案吗?也许是一些通过套接字处理 http 请求的开源示例或库(虽然不是很大很复杂,但我是菜鸟)。 最好的办法是发布示例链接,该示例读取消息正文并正确处理以下情况:内容具有分块编码、gzip 或 deflate 编码、Content-Length header 被省略(连接关闭时消息结束)。类似于 HttpWebRequest 类的源代码。
更新: 我的新函数如下所示:
int bytesRead = 0;
byte[] buffer = new byte[0x8000];
do
{
try
{
bytesRead = this.socket.Receive(buffer);
if (bytesRead <= 0) break;
else
{
this.m_responseData.Write(buffer, 0, bytesRead);
if (this.m_inHeaders == null) this.GetHeaders();
}
}
catch (Exception exception)
{
throw new Exception("Read response failed", exception);
}
}
while ((this.m_inHeaders == null) || !this.isResponseBodyComplete());
其中 GetHeaders()
和 isResponseBodyComplete()
使用带有已接收数据的 m_responseData
(MemoryStream
)。
最佳答案
我建议您不要自己实现它 - HTTP 1.1 协议(protocol)非常复杂,需要几个人月才能完成。
问题是,是否有 .NET 的 HTTP 请求协议(protocol)解析器?这个问题已经在 SO 上被问到,在答案中你会看到一些建议,包括处理 HTTP 流的源代码。
Converting Raw HTTP Request into HTTPWebRequest Object
编辑:转子代码相当复杂,难以像网页一样阅读/导航。但是,添加 SOCKS 支持的实现工作仍然比自己实现整个 HTTP 协议(protocol)要低得多。最多几天之内,您就会得到一些您可以依赖的东西,这些东西基于久经考验的实现。
请求和响应从 Connection
类中的 NetworkStream
、m_Transport
读取/写入。这在这些方法中使用:
internal int Read(byte[] buffer, int offset, int size)
//and
private static void ReadCallback(IAsyncResult asyncResult)
都在http://www.123aspx.com/Rotor/RotorSrc.aspx?rot=42903
套接字创建于
private void StartConnectionCallback(object state, bool wasSignalled)
因此您可以修改此方法以创建到您的 socks 服务器的套接字,并进行必要的握手以获得外部连接。其余代码可以保持不变。
我在网上浏览网页大约 30 分钟后就获得了这些信息。如果将这些文件加载到 IDE 中,速度应该会快得多。通读这段代码似乎是一种负担 - 毕竟,阅读代码比编写代码要难得多,但您只是对已经建立的工作系统进行微小的更改。
为确保更改在所有情况下都有效,明智的做法是在连接断开时也进行测试,以确保客户端使用相同的方法重新连接,从而重新建立 SOCKS 连接并发送 SOCKS 请求.
关于c# - 如何使用 Socket 接收 HTTP 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2945724/