通过 HTTP 代理进行双向通信

d0m*_*d0m 5 c# proxy http

我试图想出最合适的方法来通过 HTTP 代理建立双向套接字连接 - 假设这是一个 telnet 风格的协议。不幸的是,除了我无法预测的任何其他未来身份验证机制之外,我还需要支持 NTLM 身份验证(使用代理)以及基本身份验证和摘要身份验证。

如果只是基本和摘要,我会自己处理连接,但我真的不想陷入 NTLM 的泥潭。看看底层的 AuthenticationManager API,它看起来与 HttpWebRequest 非常相关,所以如果我使用套接字/tcpclient/任何东西,甚至编写新的 WebRequest 派生,我就无法利用该功能。

使用 HttpWebResponse 会产生一个无法写入的流,在检索响应流后使用 RequestStream 会产生并发 io 异常。

在尝试了我能想到的所有可能性之后,我想出了一些令人讨厌的代码,这些代码获取与 HttpWebRequest 关联的 NetworkStream,该 HttpWebRequest 允许两种方式通信:

  .....
  HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
  Stream str = resp.GetResponseStream();

  System.Type type = str.GetType();
  PropertyInfo info = type.GetProperty("Connection", BindingFlags.NonPublic|BindingFlags.Instance| BindingFlags.Public);
  object obj = info.GetValue(str, null);
  type = obj.GetType();
  info = type.GetProperty("NetworkStream", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
  object obj2 = info.GetValue(obj, null);
  NetworkStream networkStream = obj2 as NetworkStream;
Run Code Online (Sandbox Code Playgroud)

我对此相当反感(它一开始就不能与 Mono 一起工作),所以我想知道是否有更好的方法使用公共 API,这将允许我利用代理身份验证的内置运行时功能。

Pau*_*ler 1

HTTP 有两种方式。客户端可以使用 HTTP GET 发送无数据请求(尽管即使如此,数据也可以放入 URL 或标头中),也可以使用 HTTP POST 发送数据,然后服务器发送带有标头和数据的响应。

如果当您说“双向”时,您想到的更像是一个简单的 TCP 套接字,客户端和服务器可以随意读写,那么抱歉,但这不是 HTTP 所做的。客户端发送请求,服务器感知响应。就这样。从技术上讲,如果您没有客户端 API 阻碍,强制执行 HTTP 的预期约束,并且您可以构建自己的非标准服务器,则可以在单个 HTTP 中进行多个客户端 <-> 服务器交换请求,但到那时它就不再是真正的 HTTP,而是一个带有类似 HTTP 握手的 TCP 连接,并且您的代理甚至可能不允许它。

也就是说,听起来您根本不需要写入响应流,要么您很困惑并且只需要执行 POST(请参阅 GetRequestStream),要么您只是有点困惑并且您处理完响应后即可发送新请求。一旦您对获得的 WebResponse 调用了 .Close 方法,您甚至可以重用相同的 HttpWebRequest 实例。所有这一切都将发生在同一个 TCP 套接字上(如果您的服务器和代理支持它)。

好吧,我希望这一切都有意义。如果它没有以某种方式回答您的问题,只需提供更多关于您在“双向”通信方面想要实现的目标的详细信息。我知道您必须通过带有 HTTP 身份验证要求的 HTTP 代理,这会限制很多事情。