如何使用Socket接收HTTP消息

Pom*_*oma 8 .net c# sockets http

我正在Socket为我的网络客户端使用课程.我无法使用,HttpWebRequest因为它不支持socks代理.所以我必须自己解析标题并处理分块编码.对我来说最困难的是确定内容的长度,所以我必须逐字节地读取它.首先,我必须使用ReadByte()查找最后一个标题("\ r \n\r \n"组合),然后检查正文是否具有传输编码.如果它,我必须阅读块的大小等:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但这种方法的表现非常糟糕.你能提出更好的解决方案吗 也许一些开源示例或库通过套接字处理http请求(虽然不是很大很复杂,我是菜鸟).最好的方法是将链接发布到读取消息体的示例并正确处理以下情况:内容具有chunked-encoding,gzip或deflate编码,省略Content-Length头(消息在连接关闭时结束).类似于HttpWebRequest类的源代码.

Upd: 我的新功能如下所示:

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());
Run Code Online (Sandbox Code Playgroud)

where GetHeaders()isResponseBodyComplete()use m_responseData(MemoryStream)已经收到的数据.

mdm*_*dma 9

我建议你不要自己实现 - HTTP 1.1协议足够复杂,使这个项目成为几个人月.

问题是,是否有针对.NET的HTTP请求协议解析器?这个问题已在SO上提出,在答案中你会看到几个建议,包括处理HTTP流的源代码.

将原始HTTP请求转换为HTTPWebRequest对象

编辑:转子代码相当复杂,难以像网页一样阅读/导航.但是,添加SOCKS支持的实现工作要比自己实现整个HTTP协议要低得多.您可以在几天内完成一些您可以依赖的工作,这是基于经过实践检验的实施.

请求和响应是从/写入到读NetworkStream,m_TransportConnection类.这用于以下方法:

internal int Read(byte[] buffer, int offset, int size) 
//and
private static void ReadCallback(IAsyncResult asyncResult)
Run Code Online (Sandbox Code Playgroud)

两者都在http://www.123aspx.com/Rotor/RotorSrc.aspx?rot=42903

套接字是在.中创建的

private void StartConnectionCallback(object state, bool wasSignalled)
Run Code Online (Sandbox Code Playgroud)

因此,您可以修改此方法以创建到socks服务器的Socket,并执行必要的握手以获取外部连接.其余代码可以保持不变.

我在大约30分钟的时候在网页上查看了这个信息.如果将这些文件加载​​到IDE中,这应该会快得多.阅读这段代码似乎是一种负担 - 毕竟,阅读代码要比编写代码要困难得多,但是你只是对已经建立的工作系统做了很小的改动.

为了确保更改在所有情况下都有效,最好还测试连接何时断开,以确保客户端使用相同的方法重新连接,从而重新建立SOCKS连接并发送SOCKS请求.