2012-09-28 55 views
5

我正在创建一个代理服务器,它监听特定端口上的传入连接。连接通常是Http请求(GET/POST)。不能决定是否应该选择HttpListener或套接字。我将修改代理中的HttpRequests,然后将其转发到最终目的地。Sockets vs HttpListener

什么时候你更喜欢HttpListener而不是Sockets。每个的好处是什么?

+0

解析/修改HTTP标头,阅读的内容,处理分块传输等与HttpListener简单得多。 –

+0

你打算对HttpRequests进行什么样的修改? –

+0

我将改变HostHeader,重定向一些请求等 – NewUnhandledException

回答

13
  • 的HttpListener
    • 优点允许使用HTTP.SYS其他进程端口共享(包括使用HttpListener或IIS那些,只要该前缀是唯一的)
    • Http.sys的使用I/O完成端口为你;很难自己设置而不使用TcpListener
    • HttpListener解析HTTP标头并为响应创建HTTP标头
    • 为您提供了一组非常类似于ASP.Net中的标头的类,本地主机客户端通过HTTP发送大的有效载荷相比较,引起来进行这些有效载荷的数个附加拷贝的TcpListener或单声道的HttpListen - 饼干等
  • HttpListener
    • 主要的缺点呃在Windows上。如果需要每个CPU的最大吞吐量,则应避免在同一台机器上的进程之间发送大型(例如超过5 MB)的POST主体。考虑使用内存映射文件(本质上是共享内存)。当客户机和服务器位于不同的机器上时,这些额外的副本不成问题。
    • 不允许显式控制TCP套接字保持打开状态的时间; http.sys为你管理这个(这通常不是一个巨大的缺点,但它只是要注意的东西)
    • 头/ cookie类中的任何错误都会咬你;例如设置多个cookie会导致HttpListener返回一个包含多个cookie的Set-Cookie头,这个IE会处理,但Chrome会完全忽略(您必须手动推送cookie并添加您自己的Set- Cookie头的工作,解决这个问题)
  • 优势的TcpListener
    • 的像HttpListener,这实现了I/O完成端口为您
    • 如果你想为一个连接只做一次(如复auth),你可以这样做,因为你知道何时打开套接字;但是,您可能不希望依靠这种因其他原因(代理服务器和负载平衡器可以在同一插座发送来自多个用户的请求)的TcpListener对比的
  • 缺点HttpListener
    • 你必须提供一个HTTP头解析器
    • 您必须验证HTTP请求是轧制对自己
      • 无有效
    • 优势这100%是我可以想到,与使用TcpListener相比
  • 将这100%自行滚动的缺点
    • 您可能会在您的网络层代码中引入大量不必要/不正确的锁,这些锁在一次测试单个请求的性能时不会导致任何问题,但会导致负载下的性能真正受损。这需要一段时间才能找到并修复它们。
    • 我们在项目中自行推出了这个功能,并且我们实现了与HttpListener相同的性能,其中有更多的编码月份和不可维护的结果代码库。我们将其解开,并用HttpListener替换了所有的自定义代码,没有任何负面的性能影响,而且维护的代码也少得多。

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

上HttpListener的本地机器性能赤字VS Mono的HttpListener更多细节从这里我的一个同事: https://www.linkedin.com/pulse/http-inefficiency-dominika-blach

+0

很好的答案。在我的情况下,我想知道为什么我的客户在几百个连接后停止发送消息。我使用HttpListener作为客户端的WebRequest服务器。过了一段时间,他们只是简单的停下来,没有错误,看起来没有资源可用。使用'ServicePointManager.DefaultConnectionLimit'和'ServicePointManager.MaxServicePoints'来玩这个功能并没有帮助,所以在几百次连接之后,我得到了同样的错误。我尝试过KeepAlive,但没有运气。任何想法?谢谢。 – GBrian

+2

您很可能没有在一端或两端正确关闭请求和响应,或者您在客户端使用了线程池(例如通过使用定时器),并且正在从该线程池线程中抛出异常。一旦线程池线程完成,它就不会被重新创建。一旦用完线程池线程,任何使用它们的对象(如Timer对象)都不再有效。 – huntharo

+0

检查我发布的HttpListener示例代码,作为以下问题的答案。看看你是否以相同的方式处理请求,或者使用它来创建服务器的新版本,并查看问题是否存在。 http://stackoverflow.com/questions/10485985/bad-performance-when-offering-files-to-download-with-httplistener/19202175#19202175 – huntharo