7

我正在创建一个代理,它在特定端口上侦听传入连接。连接通常是 Http 请求 (GET/POST)。无法决定我应该选择 HttpListener 还是 Sockets。我将修改代理中的 HttpRequest,然后将其转发到最终目的地。

你什么时候更喜欢 HttpListener 而不是 Sockets。各有什么好处?

4

1 回答 1

20
  • HttpListener 的优点
    • 允许使用 http.sys 与其他进程共享端口(包括使用 HttpListener 或 IIS 的进程,只要前缀是唯一的)
    • Http.sys 为您使用 I/O 完成端口;不使用 TcpListener 很难自己设置
    • HttpListener 解析 HTTP 标头并为响应创建 HTTP 标头
    • 为您提供一组非常类似于 ASP.Net 中公开标头、cookie 等的类。
  • HttpListener 的缺点
    • 主要- 与 Windows 上的 TcpListener 或 Mono 的 HttpListener 相比,Localhost 客户端通过 HTTP 发送大型有效负载会导致这些有效负载的多个额外副本。如果需要每个 CPU 的最大吞吐量,则应避免在同一台机器上的进程之间发送大的(例如超过 5 MB)POST 正文。考虑改用内存映射文件(本质上是共享内存)。当客户端和服务器在不同的机器上时,这些额外的副本不是问题。
    • 不允许明确控制 TCP 套接字打开的时间;http.sys 为您管理这个(这通常不是一个巨大的缺点,但这只是需要注意的事情)
    • 标头/cookie 类中的任何错误都会咬你;例如设置多个 cookie 将导致 HttpListener 返回一个包含多个 cookie 的单个 Set-Cookie 标头的问题,IE 将处理但 Chrome 将完全忽略(然后您必须手动滚动 cookie 并添加您自己的 Set-解决此问题的 Cookie 标头)
  • TcpListener 的优点
    • 与 HttpListener 一样,它为您实现 I/O 完成端口
    • 如果您想为连接做一次事情(例如检查身份验证),您可以这样做,因为您知道套接字何时打开;但是,由于其他原因,您可能不想依赖它(代理和负载均衡器可能会通过同一个套接字发送来自多个用户的请求)
  • TcpListener 与 HttpListener 的缺点
    • 您必须提供 HTTP 标头解析器
    • 您必须验证 HTTP 请求是否有效
  • 自己滚动 100% 的优势
    • 与使用 TcpListener 相比,我没有想到
  • 自己滚动 100% 的缺点
    • 您可能会在网络层代码中引入许多不必要/错误的锁,这在一次测试单个请求的性能时不会造成任何问题,但会导致负载下的性能真正受到影响。找到这些并修复它们需要一段时间。
    • 我们确实在一个项目中自己实现了这一点,并且我们实现了与 HttpListener 相同的性能,但需要更多个月的编码和无法维护的代码库。我们将其删除并用 HttpListener 替换了所有自定义代码,而不会对性能产生任何负面影响,并且需要维护的代码也大大减少。

2016 年 11 月更新:HttpListener 在接收来自远程机器的流量时效果很好。但是,当客户端位于 localhost 上时,对于大型有效负载,从性能角度来看,HttpListener 是一个糟糕的选择。造成这种情况的部分原因是 HttpListener 使用 http.sys,它是一个内核模块,并且显然该实现导致需要制作几个额外的主体数据副本。例如,在 C# 中将 100 MB 从一个数组复制到另一个数组需要 35 毫秒,而将 100 MB 从本地客户端发布到 HttpListener 需要 350 毫秒(是的,长 10 倍)。在这种情况下切换到 Mono 的 HttpListener 会将时间减少到 250 毫秒。将 TcpListener 与 Socket 客户端一起使用需要 180 毫秒。使用 MemoryMappedFiles 将套接字的使用换成 CircularBuffer 需要 55 毫秒。因此 HttpListener 没有 从本地机器访问时,对于大型有效负载来说效果不佳。注意:如果您尝试重现此测试,则需要注意测量时间差。Stern 开始发送数据,并且当数组完成填充在接收过程中,因为一些 Send/Write 方法几乎立即返回而不发送任何数据(您可以通过发送一个零数组然后从其中写入一个来证明这一点数组的背面朝向前面;您将收到几乎所有的,证明数据直到函数返回后很久才发送)。

我的一位同事在此处提供了有关 HttpListener 与 Mono 的 HttpListener 的本地机器性能缺陷的更多详细信息: https ://www.linkedin.com/pulse/http-inefficiency-dominika-blach

于 2013-09-28T23:34:05.793 回答