zoukankan      html  css  js  c++  java
  • html5+js+.Net的即时多人聊天

            今天看了下websocket的知识,了解到这是html5新增的特性,主要用于实时web的通信。之前客户端获取服务端的数据,是通过客户端发出请求,服务端进行响应的模式,或者通过ajax每隔一段时间从后台发出请求,然后更新页面的信息,这种轮询的方式使得用户感觉页面是“实时响应”的,这样做虽然简单但未免有些暴力,另外每次请求都会有TCP三次握手并且附带了http头信息,服务器表示压力很大,这就造成了性能上和延迟的问题。

            后来的技术方案中又出现了长轮询、Comet、浏览器插件(flash)和Java等来实现服务器往客户端推送消息,但都有一些弊端。

            WebSocket的出现,意味着另一种解决方案,其提供了基于TCP的双向的、全双工(发送数据的同时也能够接受数据,两者同步进行)的socket连接。使用websocket,一旦服务端和客户端之间完成握手,信息就可以随意往来两端,而不用附件那些无用的http头信息,降低了带宽的占用,提高了性能,降低了延时。但其缺陷是浏览器的支持不够,比如IE,到了IE10才支持。

            现在就通过一个简单的例子来讲讲其运用过程,先上下效果图:

    即时通讯2

             项目的环境:.NET 4.5 +MVC 4 +JQuery+HTML5+VS2013+IE11     

    核心的实现过程,分以下几步:

    1、websocket的创建、发送消息、接受消息、关闭

    2、服务端的响应

            下面针对上面的步骤,具体讲解下:

    1、websocket的创建、发送消息、接受消息、关闭

    websocket里包含的几个重要事件如下图: onopen onmessage onerror onclose;

    image003

               websocket的创建: 这时连接会发送到服务端后台代码,进行客户端和服务端的握手,如果握手成功,则会触发onopen事件,表示连接建立;如果连接失败,就会执行onerror事件,随后执行onclose事件。当客户端获取到服务端推送的消息后,就会执行onmessage事件。

        try{
            if ("WebSocket" in window) {   //判断浏览器是否支持WebSocket
                socket = new WebSocket("ws://localhost:13458/Socket/SocketHandler.ashx"); //socket连接服务端地址
            }
        }
        catch(ex)
        {
            log("您的浏览器不支持WebSocket,请切换到更高版本 或用chrome firefox");
            return;
        }
    
        //相应的socket事件 
        //socket建立连接
        socket.onopen = function () {
            //连接成功,将消息广播出去
            isSocketConnect = true;
            $("#btnWs").val("断开");
            sendSocketMessage(Event,"进入聊天室");
        }
        //socket得到服务端广播的消息
        socket.onmessage = function (event) {
            Log(event.data);
        }
        //socket连接关闭
        socket.onclose = function () {
            Log("socket closed!");
        }
        //socket连接出现错误
        socket.onerror = function (event) {
            Log("socket connect error");
        }
               

              当然客户端也可以往服务端发送消息,发送事件便是socket.send(data);data代表发送给服务端的数据:具体代码如下

    if (socket.readyState == WebSocket.OPEN) {
            if ($("#txtMsg").val() == "") {
                if (!msg) {
                    return; //空文本不发送消息
                }
            }
            //如果未输入用户名,根据当前时间生成游客昵称
            if ($("#userName").val() == "") {
                var d = new Date();
                $("#userName").val("游客" + d.getMinutes() + "_" + d.getSeconds() + "_" + d.getMilliseconds());
            }
            if (!msg) {
                msg = "" + $("#userName").val() + ":" + "<div class='divChat'>" + $("#txtMsg").val() + "</div>";
            }
            else {
                msg = "" + $("#userName").val() + " " + msg;
            }
            socket.send(msg);
            $("#txtMsg").val(""); //清空已输入的数据
            $("#txtMsg").focus();
        }

            2、服务端的响应

            这里我们添加一般处理程序来进行响应和推送客户端消息,其中有一点要处理的是 我们要实现即时多人聊天,就要把客户端发过来的消息广播到其他客户端,这里实现原理也很简单,就是把所有的连接用list存起来,然后遍历list集合,将消息发送给各个客户端。具体实现代码如下:

        public class SocketHandler : IHttpHandler
        {
            //用来存储当前所有连接的客户单 
            public static List<WebSocket> WebSocketList;
            public void ProcessRequest(HttpContext context)
            {
                if (WebSocketList == null)
                {
                    WebSocketList = new List<WebSocket>();
                }
                HttpContext.Current.AcceptWebSocketRequest(async (contexts) =>
                {
                    WebSocket socket = contexts.WebSocket;
                    while (true)
                    {
                        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
                        CancellationToken token;
                        WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, token);
                        //获取客户端发过来的消息
                        string clientMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
    
                        if (socket.State == WebSocketState.Open)
                        {
                            //重新组织消息,发送给客户端
                            clientMessage = DateTime.Now.ToString() + "           " + clientMessage;
                            buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(clientMessage));
                            //如果该客户端为初次加入,添加到用户列表;
                            if (!WebSocketList.Contains(socket))
                            {
                                WebSocketList.Add(socket);
                            }
                            //将消息进行广播
                            foreach (WebSocket item in WebSocketList)
                            {
                                await item.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }
                        }
                        if (socket.State == WebSocketState.CloseReceived)
                        {
                            //客户断开的时候,要从列表中移除
                            WebSocketList.Remove(socket);
                        }
                    }
                });
            }

             参考资料:使用 HTML5 WebSocket 构建实时 Web 应用

             源码下载

             ps:离职了,找工作中……广州/深圳  围观简历

             喜欢就动动手指支持下!您的支持是我最大动力!

  • 相关阅读:
    范式理论
    事务
    触发器练一练
    Javascript模块化编程(三):require.js的用法
    Javascript模块化编程(二):AMD规范
    Javascript模块化编程(一):模块的写法
    什么是比特币?这可能是最通俗易懂的答案了
    Apache服务器的Options 的 Indexes FollowSymLinks详解
    机器学习进阶-图像金字塔与轮廓检测-图像金字塔(拉普拉斯金字塔)
    机器学习进阶-图像金字塔与轮廓检测-图像金字塔-(**高斯金字塔) 1.cv2.pyrDown(对图片做向下采样) 2.cv2.pyrUp(对图片做向上采样)
  • 原文地址:https://www.cnblogs.com/flowwind/p/3353139.html
Copyright © 2011-2022 走看看