当前位置:  开发笔记 > 编程语言 > 正文

套接字vs HttpListener

如何解决《套接字vsHttpListener》经验,为你挑选了1个好方法。

我正在创建一个代理,它侦听特定端口的传入连接.连接通常是Http请求(GET/POST).不能决定我应该选择HttpListener还是套接字.我将修改代理中的HttpRequests,然后将其中继到最终目的地.

你什么时候喜欢HttpListener over Sockets.每个有什么好处?



1> huntharo..:

HttpListener的优点

允许使用http.sys与其他进程共享端口(包括那些使用HttpListener或IIS的进程,只要前缀是唯一的)

Http.sys为您使用I/O完成端口; 不使用TcpListener就很难自己设置它

HttpListener解析HTTP标头并为响应创建HTTP标头

为您提供一组类似于ASP.Net中的那些暴露标题,cookie等的类.

HttpListener的缺点

MAJOR - 与Windows上的TcpListener或Mono的HttpListener相比,通过HTTP发送大型有效负载的Localhost客户端会导致这些有效负载的几个额外副本.如果需要每个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在从远程计算机接收流量时运行良好.但是,当客户端在localhost上时,对于大型有效负载,HttpListener在性能方面是一个糟糕的选择.造成这种情况的部分原因是因为HttpListener使用的是http.sys,这是一个内核模块,显然这个实现会导致身体数据的几个额外副本.例如,在C#中将100 MB从一个阵列复制到另一个阵列需要35 ms,而从本地客户端向HttpListener发送100 MB需要350 ms(是的,长10倍).在这种情况下切换到Mono的HttpListener会将时间减少到250 ms.将TcpListener与Socket客户端一起使用需要180毫秒.使用MemoryMappedFiles更换CircleBuffer的套接字使用需要55毫秒.因此,HttpListener没有 从本地计算机访问时,对于大型有效负载运行良好.注意:如果您尝试重现此测试,则需要注意测量时差.Stern开始发送数据并在接收过程中填充数组时,因为一些发送/写入方法几乎立即返回而不发送任何数据(您可以通过发送一个零数组然后从阵列的后面朝向前方;您将接收几乎所有的,证明数据在函数返回后很久才发送).

有关HttpListener与Mono的HttpListener的本地机器性能不足的详细信息来自我的一位同事:https: //www.linkedin.com/pulse/http-inefficiency-dominika-blach


您很可能没有在一端或两端正确关闭请求和响应,或者您在客户端使用了线程池(例如使用计时器),并且您正在从该线程池线程中抛出异常.一旦线程池线程完成,它就永远不会重新创建.一旦用完线程池线程,使用它们的任何东西(如Timer对象)都不再有效.
推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有