zoukankan      html  css  js  c++  java
  • C++之Effective STL

     今天看了下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:离职了,找工作中……广州 围观简历

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

     

    C++之Effective STL学习笔记Item21

     

    好了,先贴一段英文,真心不想翻译过来,而且感觉也翻译不到那么到位:

    The STL is awash in comparisons of objects to see if they have the same value. For example, when you ask find to locate the first object in a range with a particular value, find has to be able to compare two objects to see if the value of one is the same as the value of the other. Similarly, when you attempt to insert a new element into a set, set::insert has to be able to determine whether that element’s value is already in the set.

    The find algorithm and set’s insert member function are representative of many functions that must determine whether two values are the same. Yet they do it in different ways. find’s definition of “the same” is equality, which is based on operator==. set::insert’s definition of “the same” is equivalence, which is usually based on operator<.

    Operationally, the notion of equality is based on operator==. If the expression “x == y” returns true, x and y have equal values, otherwise they don’t.

    x and y have equivalent values with respect to operator< if the following expression is true:

    !(x < y) && !(y < x)

     好了,关于等价和等值的讨论,我们先到此为止。我们引入下一话题,假设我们现在创建如下一个set:

    set<int, less_equal<int> > s; // s is sorted by “<=”

    向其中插入10:

    s.insert(10);

    然后再向其插入10,我们知道,set中的元素是没有重复的,所以程序会判断10是否已经在当前set中,为了方便说明,我们把第一个插入的10称为10A,第二个称为10B。set的判断过程会是10A和10B是否是一样的,set所定义的一样就是我们之前提到的equivalence

    那么程序中的less_equal是怎么来判断的呢?我们根据上面的推导,一个合理的推导,set可能是这样来判断的:

    !(10A <= 10B) && !(10B <= 10A)      // test 10A and 10B for equivalence

    当然上头的判定的结果为:!(true) && !(true) ,等价于 false && false,所以最终的结果会是false,也就是说,判定结果告诉我们,10A和10B is not equivalent!然后10B,也就是10会被再一次插入到set中,oh, no!

    好了,这只是个玩笑,set可不会弱到如此地步,set中是不会存在重复元素的。小伙伴们肯定觉得疑惑了,这说了半天有毛用啊,set又不会使用less_equal这样的顺序,因为压根就不允许equal的情况发生,你这不是找别扭呢嘛!

    别急,set有不重复这个特性,那么要是是个multiset呢,按照这个思路,这样的操作一定会成功,会认为是两个不同的元素插入到multiset内部,假设我们在后面需要做equal_range的相关操作(it identifies a range of equivalent values),问题就大了!

    哈哈,和大家开了个很大的玩笑,STL是经过千锤百炼的,怎么可能存在这样傻的问题!关于这个问题SGI是最权威的了,我们可以去SGI查查,看到底是怎么回事!还真有,关键字:Strict Weak Ordering,好了让我们看看是怎么解决这个问题的:

    image

    明白了吧,人家是避免<=这样的比较出现,怎样避免?我目前认为避免的意思就是不能这样,这样就不行,看代码吧:

    multiset<int, less_equal<int> > s;
    s.insert(10);
    s.insert(10);

    这段代码编译通过,但是执行时会报assert错误!我没有搞清楚其中的原理,继续研究吧!

    好了,绕了这么一大圈,其实就是想告诉你,在实现自己的类似less_equal仿函数的时候,一定要留神了,千万不要存在这样的bug!

    感谢大家的阅读,希望能帮到大家!

    Published by Windows Live Writer.

    作者: 薛定谔の喵 
    出处: http://www.cnblogs.com/berlin-sun/ 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

     
     
    标签: C++STLsetless_equal
     
    分类: MVCHTML5
  • 相关阅读:
    将字符串格式化为csv数据
    以RTMP的方式播放录制好的视频
    as3signals的使用介绍
    rootkit hook之[四] IDT Hook
    .net调试WEB程序时页面无法显示的原因分析及解决办法
    rootkit hook之[六] sysenter Hook
    CUDA初探:GPU的并行计算
    rootkit hook 之[五] IRP Hook全家福
    rootkit之[七]IAT Hook HybridHook之终极打造
    CUDA初探:CUDA的初始化
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3356334.html
Copyright © 2011-2022 走看看