通过HTTP请求Websocket

原理:客户端B(Client/Browser)通过websocket向服务端S发起连接,服务端保存这个websocket连接。当浏览器A(Browser)向服务端发起HTTP请求时,服务端S接收HTTP请求并通过websocket向客户端B返回消息。

流程图:

 

客户端B的代码:用html实现,用于发送websocket请求和接收。

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <title>websocket client</title>
    <script type="text/javascript">
        //**************zzt****************
        var webSocket;
        //HTTP处理程序的地址
        var handlerUrl = "ws://localhost:8082/api/Values";

        function doConnection() {
            InitWebSocket();
        }

        function SendData() {
            var input = document.getElementById('sendText');
            //初始化WebSocket
            InitWebSocket();
            //如果WebSocket打开,发送数据
            if (webSocket.OPEN && webSocket.readyState == 1) {
                if (input.value != "")
                    webSocket.send(input.value);
            }

            //如果WebSocket关闭,显示消息
            if (webSocket.readyState == 2 || webSocket.readyState == 3) {
                alert("WebSocket关闭了,无法发送数据");
            }
        }

        function CloseWebSocket() {
            webSocket.close();
            webSocket = undefined;
        }

        function InitWebSocket() {

            //如果WebSocket对象未初始化,我们将初始化它
            if (webSocket == undefined) {
                webSocket = new WebSocket(handlerUrl);

                //打开连接处理程序
                webSocket.onopen = function () {
                    alert("WebSocket已连接");
                };

                //消息数据处理程序
                webSocket.onmessage = function (e) {
                    var label = '<li>' + e.data + '</li>';
                    $("#receiveText").append(label);
                };

                //关闭事件处理程序
                webSocket.onclose = function () {
                    alert("WebSocket closed.");
                };

                //错误事件处理程序
                webSocket.onerror = function (e) {
                    alert(e.message);
                };
            }
            else {
                //webSocket.open();没有open方法
            }
        }

        function doDeleteConnection(devid) {
            //初始化WebSocket
            InitWebSocket();

            //如果WebSocket打开,发送数据
            if (webSocket.OPEN && webSocket.readyState == 1) {

                webSocket.send("DelConnection^" + devid);
            }

            //如果WebSocket关闭,显示消息
            if (webSocket.readyState == 2 || webSocket.readyState == 3) {
                //document.getElementById("di_span").innerText = "WebSocket关闭了,无法发送数据";
                alert("WebSocket关闭了,无法发送数据");
            }
        }
        //**************zztend*************

    </script>
</head>
<body>
    <form id="sendForm">
        <input id="sendText" placeholder="Text to send" />
        <button type="button" onclick="SendData();">发送</button>
        <button type="button" onclick="doConnection();">连接</button>
        <button type="button" onclick="CloseWebSocket();">关闭</button>
        <br />
        <ul id="receiveText"></ul>
    </form>
</body>
</html>

客户端A的代码:同样用HTML实现,用于发送Http请求。

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <title>http client</title>
    <script type="text/javascript">
        function SendData() {
            var sendtext = $("#sendText").val();
            $.ajax({
                type: 'GET',
                url: 'http://localhost:8082/api/Values?text=' + sendtext,
                dataType: "jsonp",  //数据格式设置为jsonp
                jsonp: "callback", //Jquery生成验证参数的名称
                success: function (e) {

                }
            });
        }
    </script>
</head>
<body>
    <form id="sendForm">
        <input id="sendText" placeholder="Text to send" />
        <button type="button" onclick="SendData();">发送</button>
    </form>
</body>
</html>

服务端S的代码:用Web API实现,用于接收HTTP和Websocket,还有返回Websocket消息。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.WebSockets;

namespace WebSocketServer.Controllers
{
    public class ValuesController : ApiController
    {
        private static Dictionary<string, object> ws = new Dictionary<string, object>();
        // GET api/values
        public HttpResponseMessage Get()
        {
            //检查 查询是否是WebSocket请求
            if (HttpContext.Current.IsWebSocketRequest)
            {
                //如果是,我们附加异步处理程序
                HttpContext.Current.AcceptWebSocketRequest(ProcessWSMsg);
            }
            else
            {
                //否则,认为是HTTP请求
                if (ws.Count > 0)
                {
                    var WebSocket = ws["1"];
                    var Content = HttpContext.Current.Request["text"];
                    BackWs((WebSocket)WebSocket, Content);

                }
            }
            return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
        }

        private async Task ProcessWSMsg(AspNetWebSocketContext arg)
        {
            //获取当前的WebSocket对象
            WebSocket webSocket = arg.WebSocket;
            if (ws.ContainsKey("1"))
                ws["1"] = webSocket;
            else
                ws.Add("1", webSocket);
            /*
             * 我们定义一个常数,它将表示接收到的数据的大小。 它是由我们建立的,我们可以设定任何值。 我们知道在这种情况下,发送的数据的大小非常小。
            */
            const int maxMessageSize = 1024;

            //received bits的缓冲区
            var receivedDataBuffer = new ArraySegment<Byte>(new Byte[maxMessageSize]);

            var cancellationToken = new CancellationToken();

            //检查WebSocket状态
            while (webSocket.State == WebSocketState.Open)
            {
                //读取数据 
                WebSocketReceiveResult webSocketReceiveResult = await webSocket.ReceiveAsync(receivedDataBuffer, cancellationToken);

                //如果输入帧为取消帧,发送close命令
                if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationToken);
                }
                else
                {
                    byte[] payloadData = receivedDataBuffer.Array.Where(b => b != 0).ToArray();

                    //因为我们知道这是一个字符串,我们转换它
                    string receiveString = System.Text.Encoding.UTF8.GetString(payloadData, 0, payloadData.Length);

                    //将字符串转换为字节数组. 
                    var newString = String.Format("Hello, " + receiveString + " ! Time {0} 消息来自客户端B", DateTime.Now.ToString());
                    Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(newString);

                    //发回数据
                    await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, cancellationToken);
                }

            }
        }

        /// <summary>
        /// 返回websocket消息
        /// </summary>
        /// <param name="webSocket"></param>
        /// <param name="Content"></param>
        private void BackWs(WebSocket webSocket,string Content)
        {
            var cancellationToken = new CancellationToken();

            Content = String.Format("Hello, " + Content + " ! Time {0} 消息来自客户端A", DateTime.Now.ToString());
            //检查WebSocket状态
            if (webSocket.State == WebSocketState.Open)
            {
                //将字符串转换为字节数组. 
                Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(Content);
                //发回数据
                webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, cancellationToken);

            }
        }

    }
}

实现效果:

posted @ 2018-12-30 18:32  漂移青春  阅读(1350)  评论(0编辑  收藏  举报