我试图想出最合适的方法来通过 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,这将允许我利用代理身份验证的内置运行时功能。
HTTP 有两种方式。客户端可以使用 HTTP GET 发送无数据请求(尽管即使如此,数据也可以放入 URL 或标头中),也可以使用 HTTP POST 发送数据,然后服务器发送带有标头和数据的响应。
如果当您说“双向”时,您想到的更像是一个简单的 TCP 套接字,客户端和服务器可以随意读写,那么抱歉,但这不是 HTTP 所做的。客户端发送请求,服务器感知响应。就这样。从技术上讲,如果您没有客户端 API 阻碍,强制执行 HTTP 的预期约束,并且您可以构建自己的非标准服务器,则可以在单个 HTTP 中进行多个客户端 <-> 服务器交换请求,但到那时它就不再是真正的 HTTP,而是一个带有类似 HTTP 握手的 TCP 连接,并且您的代理甚至可能不允许它。
也就是说,听起来您根本不需要写入响应流,要么您很困惑并且只需要执行 POST(请参阅 GetRequestStream),要么您只是有点困惑并且您处理完响应后即可发送新请求。一旦您对获得的 WebResponse 调用了 .Close 方法,您甚至可以重用相同的 HttpWebRequest 实例。所有这一切都将发生在同一个 TCP 套接字上(如果您的服务器和代理支持它)。
好吧,我希望这一切都有意义。如果它没有以某种方式回答您的问题,只需提供更多关于您在“双向”通信方面想要实现的目标的详细信息。我知道您必须通过带有 HTTP 身份验证要求的 HTTP 代理,这会限制很多事情。