HTML5示例之WebSocket

Web應用程序一般有一些耗時的操做,但有些操做耗時不是很長,一分鐘以內能完成。若是採用後臺任務隊列去異步處理,這樣的用戶不能實時看到後臺處理的狀況。假若用戶觸發操做後,Web頁面可以實時看到後臺處理的進度,而且返回實時的狀態,用戶等待起來是否是感受很是棒。下面是一個HTML5+ASP.NET MVC實現的示例。html

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很簡單,以下示例封裝了一個簡單的操做。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');
    });
}

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

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

3.運行效果

相關文章
相關標籤/搜索