溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.Net實現Http長連接(Comet)

發布時間:2020-08-02 23:13:13 來源:網絡 閱讀:18468 作者:BoyTNT 欄目:編程語言

   在網上搜了搜,沒有發現C#實現http長連接的開源項目,估計是實現起來太簡單了吧。自己寫一個,不是項目中使用,純粹測試一下。


1、原理

   所謂長連接,是指客戶端以http協議連接到服務器,區別于一般的短連接,服務器不會立即返回數據,而是保持住這個連接,等到有數據時才返回。說起來簡單,但卻不能使用Sleep或者信號量的方式保持住連接,因為這么做會長時間占用線程,客戶端多時很快會占滿ASP.Net的線程池。

   ASP.Net提供了IHttpAsyncHandler接口,允許開發者以異步方式處理http請求。示意圖如下:

ASP.Net實現Http長連接(Comet)


   Http請求到達服務器后,被BeginProce***equest方法處理,它個方法要生成一個IAsyncResult對象,并將其保存到其它地方,之后返回。此時連接將保持住,但ASP.Net已經可以空出資源去處理下一個請求了。直到程序的業務邏輯觸發IAsyncResult對象的Callback,IHttpAsyncHandler對象的EndProce***equest方法才被調用,此時可以做輸出,之后這個http請求才真正結束。


2、IHttpAsyncHandler實現

using System;
using System.Web;
namespace Comet
{
    public class CometAsyncHandler : IHttpAsyncHandler
    {
        /// <summary>
        /// 請求到達時的處理方法
        /// </summary>
        public IAsyncResult BeginProce***equest(HttpContext context, AsyncCallback callback, object extraData)
        {
            //通過context可以取請求附加的數據,略
            //...
                                                                                                            
            //之后生成IAsyncResult對象,callback比較重要,調用這個回調,EndProce***equest才被觸發
            var result = new CometResult(context, callback, extraData);
            //在返回之前把剛生成的IAsyncResult對象保存起來,略
            //...
            return result;
        }
        /// <summary>
        /// 請求結束時的處理方法
        /// </summary>
        public void EndProce***equest(IAsyncResult asyncResult)
        {
            //得到對應的IAsyncResult對象
            var result = asyncResult as CometResult;
            //后續處理,如輸出內容等,略
            //...
        }
        public bool IsReusable
        {
            get { return false; }
        }
        public void Proce***equest(HttpContext context)
        {
            throw new NotImplementedException();
        }
    }
}


3、IAsyncResult實現

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,增加:

<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>節中注冊,增加:

<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方法里加忽略:

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



搞定收工,請求Data.aspx時,連接會被保持住,直到通過另一個頁面調用IAsyncResult對象的Call方法,當前連接才會返回。

簡單測試了一下,保持3000個連接很輕松,并且都能快速響應,達到了預期。由于.net有默認最大并發連接數的限制,客戶端如果開多個連接,需要把 ServicePointManager.DefaultConnectionLimit 調大一些。另外開到1300多個連接的時候就報OutOfMemoryException了,所以要多用幾臺客戶端測。




向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女