ASP.Net实现Http长连接(Comet)

简介:

   在网上搜了搜,没有发现C#实现http长连接的开源项目,估计是实现起来太简单了吧。自己写一个,不是项目中使用,纯粹测试一下。


1、原理

   所谓长连接,是指客户端以http协议连接到服务器,区别于一般的短连接,服务器不会立即返回数据,而是保持住这个连接,等到有数据时才返回。说起来简单,但却不能使用Sleep或者信号量的方式保持住连接,因为这么做会长时间占用线程,客户端多时很快会占满ASP.Net的线程池。

   ASP.Net提供了IHttpAsyncHandler接口,允许开发者以异步方式处理http请求。示意图如下:

090230336.jpg


   Http请求到达服务器后,被BeginProcessRequest方法处理,它个方法要生成一个IAsyncResult对象,并将其保存到其它地方,之后返回。此时连接将保持住,但ASP.Net已经可以空出资源去处理下一个请求了。直到程序的业务逻辑触发IAsyncResult对象的Callback,IHttpAsyncHandler对象的EndProcessRequest方法才被调用,此时可以做输出,之后这个http请求才真正结束。


2、IHttpAsyncHandler实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using  System;
using  System.Web;
namespace  Comet
{
     public  class  CometAsyncHandler : IHttpAsyncHandler
     {
         /// <summary>
         /// 请求到达时的处理方法
         /// </summary>
         public  IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback,  object  extraData)
         {
             //通过context可以取请求附加的数据,略
             //...
                                                                                                             
             //之后生成IAsyncResult对象,callback比较重要,调用这个回调,EndProcessRequest才被触发
             var  result =  new  CometResult(context, callback, extraData);
             //在返回之前把刚生成的IAsyncResult对象保存起来,略
             //...
             return  result;
         }
         /// <summary>
         /// 请求结束时的处理方法
         /// </summary>
         public  void  EndProcessRequest(IAsyncResult asyncResult)
         {
             //得到对应的IAsyncResult对象
             var  result = asyncResult  as  CometResult;
             //后续处理,如输出内容等,略
             //...
         }
         public  bool  IsReusable
         {
             get  return  false ; }
         }
         public  void  ProcessRequest(HttpContext context)
         {
             throw  new  NotImplementedException();
         }
     }
}


3、IAsyncResult实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using  System;
using  System.Web;
using  System.Threading;
namespace  Comet
{
     public  class  CometResult : IAsyncResult
     {
         #region 实现IAsyncResult接口
         public  object  AsyncState {  get private  set ; }
         public  WaitHandle AsyncWaitHandle {  get private  set ; }
         public  bool  CompletedSynchronously {  get private  set ; }
         public  bool  IsCompleted {  get private  set ; }
         #endregion
         public  AsyncCallback Callback {  get private  set ; }
         public  HttpContext Context {  get private  set ; }
         public  object  ExtraData {  get private  set ; }
         public  CometResult(HttpContext context, AsyncCallback callback,  object  extraData)
         {
             this .Context = context;
             this .Callback = callback;
             this .ExtraData = extraData;
         }
         public  Call()
         {
             if ( this .Callback !=  null )
                 this .Callback( this );
         }
     }
}


4、调用

找到对应的IAsyncResult对象,调用其Call方法即可。


5、配置文件

在<system.web>节中注册httpHandler,增加:

1
2
3
4
5
6
< system.web >
     < httpHandlers >
         <!-- 针对GET与POST两种请求,路径是Data.aspx文件,使用CometAsyncHandler处理 -->
         < add  verb = "GET,POST"  path = "Data.aspx"  type = "Comet.CometAsyncHandler, Comet" />
     </ httpHandlers >
</ system.web >


考虑到兼容IIS7,还要在<system.webServer>节中注册,增加:

1
2
3
4
5
6
7
8
9
< system.webServer >
     <!--忽略system.web中的注册-->
     < validation  validateIntegratedModeConfiguration = "false" />
     < modules  runAllManagedModulesForAllRequests = "true" />
     < handlers >
         <!--与上面完全相同-->
         < add  name = "CometHandler"  verb = "GET,POST"  path = "Data.aspx"  type = "Comet.CometAsyncHandler, Comet"  />
     </ handlers >
</ system.webServer >


6、针对MVC的特殊处理

增加HttpHandler会受mvc影响,需要在RegisterRoutes方法里加忽略:

1
2
//忽略Data.aspx
routes.IgnoreRoute( "Data.aspx/{*pathInfo}" );



搞定收工,请求Data.aspx时,连接会被保持住,直到通过另一个页面调用IAsyncResult对象的Call方法,当前连接才会返回。

简单测试了一下,保持3000个连接很轻松,并且都能快速响应,达到了预期。由于.net有默认最大并发连接数的限制,客户端如果开多个连接,需要把 ServicePointManager.DefaultConnectionLimit 调大一些。另外开到1300多个连接的时候就报OutOfMemoryException了,所以要多用几台客户端测。





     本文转自 BoyTNT 51CTO博客,原文链接:http://blog.51cto.com/boytnt/1250084,如需转载请自行联系原作者


相关文章
|
域名解析 缓存 Linux
如何让你的.NET WebAPI程序支持HTTP3?
如何让你的.NET WebAPI程序支持HTTP3?
207 2
如何让你的.NET WebAPI程序支持HTTP3?
|
中间件 Go 开发者
Go net http包
Go net http包
179 0
|
3月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
4月前
|
Go
在golang中发起http请求以获取访问域名的ip地址实例(使用net, httptrace库)
这只是追踪我们的行程的简单方法,不过希望你跟着探险家的脚步,即使是在互联网的隧道中,也可以找到你想去的地方。接下来就是你的探险之旅了,祝你好运!
168 26
|
5月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
199 35
|
9月前
|
Ubuntu Linux Shell
(已解决)Linux环境—bash: wget: command not found; Docker pull报错Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled
(已成功解决)Linux环境报错—bash: wget: command not found;常见Linux发行版本,Linux中yum、rpm、apt-get、wget的区别;Docker pull报错Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled
4202 69
(已解决)Linux环境—bash: wget: command not found; Docker pull报错Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled
|
9月前
|
JSON 数据格式
.net HTTP请求类封装
`HttpRequestHelper` 是一个用于简化 HTTP 请求的辅助类,支持发送 GET 和 POST 请求。它使用 `HttpClient` 发起请求,并通过 `Newtonsoft.Json` 处理 JSON 数据。示例展示了如何使用该类发送请求并处理响应。注意事项包括:简单的错误处理、需安装 `Newtonsoft.Json` 依赖,以及建议重用 `HttpClient` 实例以优化性能。
225 2
|
11月前
|
API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
180 0
|
数据采集 API 开发者
.NET 8新特性:使用ConfigurePrimaryHttpMessageHandler定制HTTP请求
在.NET 8中,通过`ConfigurePrimaryHttpMessageHandler`方法,开发者能更精细地控制HTTP请求,这对于构建高效爬虫尤为重要。此特性支持定制代理IP、管理Cookie与User-Agent,结合多线程技术,有效应对网络限制及提高数据采集效率。示例代码展示了如何设置代理服务器、模拟用户行为及并发请求,从而在遵守网站规则的同时,实现快速稳定的数据抓取。
215 0
.NET 8新特性:使用ConfigurePrimaryHttpMessageHandler定制HTTP请求
|
数据采集 开发框架 .NET
HttpClient在ASP.NET Core中的最佳实践:实现高效的HTTP请求
在现代Web开发中,高效可靠的HTTP请求对应用性能至关重要。ASP.NET Core提供的`HttpClient`是进行这类请求的强大工具。本文探讨其最佳实践,包括全局复用`HttpClient`实例以避免性能问题,通过依赖注入配置预设头部信息;使用代理IP以防IP被限制;设置合理的`User-Agent`和`Cookie`来模拟真实用户行为,提高请求成功率。通过这些策略,可显著增强爬虫或应用的稳定性和效率。
263 0
HttpClient在ASP.NET Core中的最佳实践:实现高效的HTTP请求

热门文章

最新文章