Web應用程序一般有一些耗時的操做,但有些操做耗時不是很長,一分鐘以內能完成。若是採用後臺任務隊列去異步處理,這樣的用戶不能實時看到後臺處理的狀況。假若用戶觸發操做後,Web頁面可以實時看到後臺處理的進度,而且返回實時的狀態,用戶等待起來是否是感受很是棒。下面是一個HTML5+ASP.NET MVC實現的示例。html
頁面包含一個文本框和一個【提交】按鈕,文本框輸入後臺要返回的消息數。前端
<h2>WebSocket</h2> <div class="form-inline"> <div class="form-group"> <label for="count">消息數</label> <input type="text" class="form-control" id="count" placeholder="服務端返回的消息數"> </div> <button class="btn btn-primary" onclick="wsTest()">提交</button> </div> <blockquote> <ol id="msg"></ol> </blockquote>
WebSocket的api很簡單,以下示例封裝了一個簡單的操做。html5
var WsUtil = { msg: document.getElementById('msg'), ws: null, connect: function (url, callback) { var _this = this; _this.msg.innerHTML = ''; _this.appendMsg('正在鏈接......', '#00f'); _this.ws = new WebSocket(url); _this.ws.onopen = function () { _this.appendMsg('客戶端已鏈接', '#00f'); if (callback) { callback(_this.ws); } } _this.ws.onmessage = function (evt) { _this.appendMsg(evt.data); } _this.ws.onclose = function () { _this.appendMsg('客戶端已斷開鏈接', '#00f'); } _this.ws.onerror = function (evt) { _this.appendMsg(evt.data, '#f00'); } }, close: function () { if (this.ws) { this.ws.close(); this.ws = null; } }, appendMsg: function (message, color) { var li = document.createElement('li'); li.style.color = color || '#000'; li.innerHTML = message; msg.appendChild(li); } } function wsTest() { var count = document.getElementById('count').value; var url = 'ws://localhost:90/html5/wstask?count=' + count; WsUtil.connect(url, function (ws) { ws.send('test'); }); }
ASP.NET MVC控制器web
public class Html5Controller : Controller { public void WsTask() { HttpContext.AcceptWebSocketRequest(ctx => { int.TryParse(ctx.QueryString["count"], out int count); return WebSocketManager.RunTask(ctx, wsm => { for (int i = 0; i < count; i++) { var message = string.Format("{0:yyyyMMdd HH:mm:ss} 消息{1}", DateTime.Now, i + 1); wsm.SendMessageAsync(message); Thread.Sleep(1000); } }); }); } }
這裏封裝了一個WebSocket管理者類。c#
public class WebSocketManager { private WebSocket socket; public WebSocketManager() { } public WebSocketManager(WebSocket socket) { this.socket = socket; } public static async Task RunTask(AspNetWebSocketContext context, Action<WebSocketManager> action) { var socket = context.WebSocket; if (socket.State == WebSocketState.Open) { var wsm = new WebSocketManager(socket); try { action(wsm); } catch (Exception ex) { await wsm.SendMessageAsync(ex.Message); } } } public Task SendMessageAsync(string message) { var content = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message)); return socket.SendAsync(content, WebSocketMessageType.Text, true, CancellationToken.None); } }