1. 程式人生 > >HTML5示例之WebSocket

HTML5示例之WebSocket

異步處理 utf8 pri context 控制 情況 -i his turn

Web應用程序通常有一些耗時的操作,但耗時不是很長,一分鐘之內能完成的。如果采用後臺任務隊列去異步處理,這樣的用戶不能實時看到後臺處理的情況。倘若用戶觸發操作後,Web頁面能夠實時看到後臺處理的進度,並且返回實時的狀態,用戶等待起來是不是感覺非常棒。

1.前端頁面和腳本

頁面包含一個文本框和一個【提交】按鈕,文本框輸入後臺要返回的消息數。

<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很簡單,如下示例封裝了一個簡單的操作。

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

2.ASP.NET MVC後端實現WebSocket請求

ASP.NET MVC控制器

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管理者類。

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

運行效果

技術分享圖片

HTML5示例之WebSocket