QtQuick 与 WebSocket 之 WebSocket 的压力测试



  • 大家好,我是萌萌哒新人~

    今天不说别的,就说说 WebSocket 吧。

    WebSocket 是一种应用层的协议,类似于 TCP 可以维持一个长连接,又可以像 http 协议那样,不要考虑包的问题(取决于实现)。

    由于我的软件工程实训是做一个论坛(功能删减许多呢)。客户端与服务端使用 WebSocket 进行通讯。

    但是没有进行压力测试。今天晚上刚好有空。就来了个简单的回写服务的压力测试。

    客户端开启大概 1300 个链接,隔 2 秒发送一个 1024 * 8 个字节的信息,服务端收到后再回写给客户端。

    以下为客户端:

    0_1466007010374_upload-70cca159-c603-4410-ab66-c2ceaac28585

    图中的方块为一个连接,数字为服务端回写信息的次数。

    运行大概 5 分钟后,有些链接就被服务端自动断开了。。

    这里的 WebSocket 的实现是 Tomcat 版本的,Tomact 版本是 8。



  • @qyvlik

    QML 的测试代码:

    import QtQuick 2.5
    import QtQuick.Controls 1.3
    import Qt.WebSockets 1.0
    
    Item {
        id: app
        visible: true
        width: 400
        height: 400
    
        Rectangle {
            anchors.fill: parent
        }
    
        Flow {
            id: flow
            anchors.fill: parent
        }
    
        Button {
            id: button
            text: "clinet: " +count
            property int count: 0
            anchors.centerIn: parent
            onClicked: {
    
                var step = 100
                while(step != 0) {
                    com.createObject(flow, {"count": count} )
                    count++;
                    step --;
                }
            }
        }
    
        Component {
            id: com
            Rectangle {
                id: root
                width: 50
                height: 50
                color: Qt.rgba(Math.random(), Math.random(), Math.random(),1)
                property int count: 0
                property int messageCount: 0
                Text {
                    anchors.centerIn: parent
                    text: parent.messageCount + ""
                    color: Qt.lighter(parent.color)
                }
    
                WebSocket {
                    id: websocket
                    // 开启wifi后的链接地址
                    url: "ws://192.168.253.1:8080/JavaWebSocket/websocket"
                    // url: "ws://localhost:8080/JavaWebSocket/websocket"
                    active: true
    
                    onStatusChanged: {
                        if(status == WebSocket.Error) {
                            console.log(websocket.errorString)
                            websocket.active = false;
                            root.destroy(1000)
                            button.count--;
                        }
                    }
                    onTextMessageReceived: {
                       // console.log(message)
                        root.messageCount++;
                    }
                }
                Timer {
                    repeat: true
                    interval: 2000 * Math.max(Math.random(), 0.9)
                    running: true
                    onTriggered: {
                        if(websocket.status == WebSocket.Open) {
                            websocket.sendTextMessage(bigMessage)
                        }
                    }
                }
            }
        }
    
    
        property string bigMessage: "";
        Component.onCompleted: {
            var step = 2048*4;
            while(step != 0) {
                bigMessage += "a"
                step --;
            }
    
            console.log(bigMessage.length)
    
        }
    
    }
    

    Java WebSocket 服务端:

    package org.gdpurjyfs.websocket;
    
    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    import javax.websocket.CloseReason;
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    @ServerEndpoint("/websocket")
    public class WebSocketServer {
    	 //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
         
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
         
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
         
        /**
         * 连接建立成功调用的方法
         * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        @OnOpen
        public void onOpen(Session session){
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        }
         
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose(CloseReason reason){
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数减1    
            System.out.println("关闭原因是:"+reason.getReasonPhrase());
            System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
         
        /**
         * 收到客户端消息后调用的方法
         * @param message 客户端发送过来的消息
         * @param session 可选的参数
         */
        @OnMessage
        public void onMessage(String message, Session session) {    	
            // System.out.println("来自客户端的消息:" + message);
            try {
    			session.getBasicRemote().sendText(message);
    		} catch (IOException e1) {
    		}
            //群发消息
    //        for(WebSocketServer item: webSocketSet){             
    //            try {
    //                item.sendMessage(item.session.getId()+": "+message);
    //                
    //            } catch (IOException e) {
    //                e.printStackTrace();
    //                continue;
    //            }
    //        }
        }
         
        /**
         * 发生错误时调用
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error){
            System.out.println("发生错误");
            // webSocketSet.remove(this);  //从set中删除
            // subOnlineCount();           //在线数减1    
            // error.printStackTrace();
        }
             
        /**
         * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
         * @param message
         * @throws IOException
         */
        public void sendMessage(String message) throws IOException{
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
     
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
     
        public static synchronized void addOnlineCount() {
        	WebSocketServer.onlineCount++;
        }
         
        public static synchronized void subOnlineCount() {
        	WebSocketServer.onlineCount--;
        }
    }
    


  • @qyvlik

    PS: 由于打算将项目从 Tomcat 的 WebSocket 移植到 Jetty 的 WebSocket 。但是我发现 Jetty 的 WebSocket 的 API 虽然很强大,但是每一个版本的 API 接口都不兼容,然后我在 MyEclipse 2014 + Jetty 7.x 以及 MyEclipse 2016 + Jetty 9.x 都无法将网上找到的 WebSocket 例子运行起来。其中 WebSocketServlet 在 Jetty 容器中加载时就会报错。(或许在 Jetty 加载 HttpServlet 子类需要另外设置一下?)


 

最近的回复

  • 这个很有意思 ^_^

    阅读更多
  • 思路:
    1.把官方时钟demo改了,加了秒针,加了壁纸,加了小萝莉
    2.QWindow窗口嵌入到桌面

    0_1533891238039_20180810_164211.gif

    改版

    去掉秒针,把小萝莉正过来,沿着表盘走

    0_1533893719543_20180810_173309.gif

    源代码

    Fork me on Gitee

    阅读更多
  • 思路:
    1.识别鼠标移动事件
    2.QPropertyAnimation实现移动动画
    3.QLabel和QMovie使用gif

    0_1533808278715_20180809_174840.gif

    阅读更多
  • 很多小软件,实现了很好的功能。给你点赞!

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔