zoukankan      html  css  js  c++  java
  • WebSocket 实现之 Tomcat

    搞定这个的过程远比想象的困难许多。网上许多教程,一一尝试,大多随着库版本的改变以及浏览器对协议支持的改变以失败告终,即使成功的也语焉不详,以下为步骤。

    1. 运行环境

    Java EE IDE

    apache-tomcat-7.0.29(7.0.27之后才支持websocket)

    IE(版本:10.0.9200.16384)

    Firefox(版本:15.0)

    Google Chrome(版本:23.0.1251.2)

    2. 详细步骤

    (1) 在Java EE IDE中,File->New->Dynamic Web Project,使其如下配置

    Target runtime中必须是Apache Tomcat v7.0,并且最好是引用7.0.29(可在New Runtime中配置)

    注意,点击Next->,再点击Next->,如下图,注意勾选Generate web.xml deployment descriptor,点击Finish

    (2) 在Java Resources下src下New->Class,如下图

    再在src下New->Class,如下图

    下面贴上上述类的代码

    package com.trump.web.servlet;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.logging.Logger;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.catalina.websocket.StreamInbound;
    import org.apache.catalina.websocket.WebSocketServlet;
    
    public class EchoServlet extends WebSocketServlet {
        private static final long serialVersionUID = -4104682919545889813L;
    
        private Logger logger = Logger.getLogger(EchoServlet.class.getName());
    
        private static List<MyMessageInbound> socketList = new ArrayList<MyMessageInbound>();
    
        @Override
        protected StreamInbound createWebSocketInbound(String subProtocol,
                HttpServletRequest request) {
            // TODO Auto-generated method stub
            logger.info("receive ws request");
            return new MyMessageInbound();
        }
    
        public static synchronized List<MyMessageInbound> getSocketList() {
            return socketList;
        }
    }
    package com.trump.web.servlet;
    
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.util.logging.Logger;
    
    import org.apache.catalina.websocket.MessageInbound;
    import org.apache.catalina.websocket.WsOutbound;
    
    public class MyMessageInbound extends MessageInbound {
        private int userIdName = 0;
        private Logger logger = Logger.getLogger(MyMessageInbound.class.getName());
    
        public int getUserIdName() {
            return userIdName;
        }
    
        protected void onOpen(WsOutbound outbound) {
            super.onOpen(outbound);
            userIdName = outbound.hashCode();
            EchoServlet.getSocketList().add(this);
            logger.info("Server onOpen");
        }
    
        protected void onClose(int status) {
            EchoServlet.getSocketList().remove(this);
            super.onClose(status);
            logger.info("Server onClose");
        }
    
        // 有二进制消息数据到达,比如音频等文件传输
        @Override
        protected void onBinaryMessage(ByteBuffer buffer) throws IOException {
            logger.info("Binary Message Receive: " + buffer.remaining());
        }
    
        @Override
        protected void onTextMessage(CharBuffer buffer) throws IOException {
            String msgOriginal = buffer.toString();
    
            int startIndex = msgOriginal.indexOf("!@#$%");
            String nikeName = msgOriginal.substring(0, startIndex);
            String textMsg = msgOriginal.substring(startIndex + 5);
            // 将字符数组包装到缓冲区中
            // 给定的字符数组将支持新缓冲区;即缓冲区修改将导致数组修改,反之亦然
    
            String countMsg = EchoServlet.getSocketList().size() + "人同时在线";
            logger.info("Server onTextMessage: " + countMsg + nikeName + ":"
                    + textMsg);
    
            String msg1 = nikeName + ": " + textMsg;
            String msg2 = "我: " + textMsg;
    
            for (MyMessageInbound messageInbound : EchoServlet.getSocketList()) {
                CharBuffer msgBuffer1 = CharBuffer.wrap(msg1);
                CharBuffer msgBuffer2 = CharBuffer.wrap(msg2);
    
                WsOutbound outbound = messageInbound.getWsOutbound();
                if (messageInbound.getUserIdName() != this.getUserIdName()) {
                    outbound.writeTextMessage(msgBuffer1);
                    outbound.flush();
                } else {
                    outbound.writeTextMessage(msgBuffer2);
                }
            }
        }
    }

    (3) 打开WebContent下WEB-INF下web.xml,编辑为

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        id="WebApp_ID" version="3.0">
        <display-name>myWebSocket</display-name>
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>default.html</welcome-file>
            <welcome-file>default.htm</welcome-file>
            <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
    
        <servlet>
            <servlet-name>echo</servlet-name>
            <servlet-class>com.trump.web.servlet.EchoServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>echo</servlet-name>
            <url-pattern>*.ws</url-pattern>
        </servlet-mapping>
    </web-app>

    (4) 右击项目myWebSocket->Run As->Run on Server,如下图,点击Finish,

    可以看到Tomacat正常运行,如下图

    (5) 在任意位置新建一个客户端,命名为client.html,内容如下

    <!DOCTYPE html>
    <html>
    <head>
    <title>Web Socket Demo</title>
    <script type="text/javascript">
        var ws = null;
        function startServer() {
            var url = "ws://127.0.0.1:8080/myWebSocket/echo.ws";
            if ('WebSocket' in window) {
                ws = new WebSocket(url);
            } else if ('MozWebSocket' in window) {
                ws = new MozWebSocket(url);
            } else {
                alert('Your browser Unsupported WebSocket!');
                return;
            }
    
            ws.onopen = function() {
                document.getElementById("content").innerHTML += 'websocket open! Welcome!<br />';
            };
            ws.onmessage = function(event) {
                document.getElementById("content").innerHTML += event.data + '<br />';
            };
            ws.onclose = function() {
                document.getElementById("content").innerHTML += 'websocket closed! Byebye!<br />';
            };
        }
    
        function sendMyMessage() {
            var nickName = document.getElementById('nickName');
            var textMessage = document.getElementById('textMessage');
            if (ws != null && textMessage.value != '') {
                ws.send(nickName.value + '!@#$%' + textMessage.value);
                textMessage.value = '';
            }
        }
    </script>
    </head>
    <body onload="startServer()">
        昵称:
        <input type="text" id="nickName" size="20" />
        <br />
        <input type="text" id="textMessage" size="20" />
        <input type="button" onclick="sendMyMessage()" value="Send">
        <div id="content"></div>
    </html>

    (6) OK!打开浏览器,输入http://localhost:8080/webSocketTest/client.html

    此时注意Tomcat打印出的信息,如下

    3. WebSocket之所以受关注,是因为它的服务器端能主动发消息给客户端,即MyMessageInbound中onOpen函数可以让服务器做想做的事情。

  • 相关阅读:
    linux笔记2.20
    新安装ubuntu后几项配置
    linux网络配置
    linux笔记2.19
    jquery在不同浏览器获取文件路径出现问题!
    软件工程师如何定义自己的职业路线
    标识符
    结对项目-四则运算 “软件”之升级版
    小学四则运算 “软件”之初版
    分布式版本控制系统Git的安装与使用
  • 原文地址:https://www.cnblogs.com/studyhs/p/2674322.html
Copyright © 2011-2022 走看看