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); } }