• 通过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);
    
                }
            }
    
        }
    }
    

    实现效果:

  • 相关阅读:
    使用ACEGI搭建权限系统:第三部分
    分支在版本树中的应用(使用subversion)
    acegi安全框架使用:第二部分
    错误数据导致java.lang.IllegalArgumentException:Unsupported configuration attributes
    移动中间件和wap网关的比较
    3年后,又回到了.net阵营
    android中listView的几点总结
    oracle相关分布式数据解决方案
    ajax实现用户名存在校验
    使用template method模式简化android列表页面
  • 原文地址:https://www.cnblogs.com/zt102545/p/13940245.html
Copyright © 2020-2023  润新知