2013年6月21日金曜日

tomcatでwebsocket

Tomcat7.0.27からwebsocketが使えるようになりました。

早速使ってみましょう。

今回はtomcat7.0.41を使用しています。

手始めにチャットを作ってみます。

①WebSocketServlet
 tomcatと言えばHttpServletを継承してサーブレットを作成しますが、
 websocketは「WebSocketServlet」を継承してサーブレットを作ります。

 public class ChatServlet extends WebSocketServlet {

②クライアントからの接続要求
 接続が来たらcreateWebSocketInboundが呼ばれます。

 @Override
 protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
  return new EchoMessageInbound(byteBufSize,charBufSize);
 }

③上記で生成するEchoMessageInboundクラスを定義します
 private static final class EchoMessageInbound extends MessageInbound {

  private String name = null;

  public EchoMessageInbound(int byteBufferMaxSize, int charBufferMaxSize) {

   super();

   setByteBufferMaxSize(byteBufferMaxSize);

   setCharBufferMaxSize(charBufferMaxSize);

  }

  @Override

  protected void onOpen(WsOutbound outbound) {

   super.onOpen(outbound);

   peers.add(this);

  }

  @Override

  protected void onClose(int status) {

   super.onClose(status);

   peers.remove(this);

  }

  @Override

  protected void onBinaryMessage(ByteBuffer message) throws IOException {

   System.out.println("onBinaryMessage");

   getWsOutbound().writeBinaryMessage(message);

  }

  @Override

  protected void onTextMessage(CharBuffer message) throws IOException {

   System.out.println("onTextMessage[" + message + "]");

   if( message.toString().indexOf("joined") > 0 ) {

    name = message.toString().split(" ")[0];

   }

   for( EchoMessageInbound u: peers ) {

    u.getWsOutbound().writeTextMessage(CharBuffer.wrap(""+message.toString()));

   }

  }

 }


これだけです。

④あとはクライアント側

websocket.js
※これはJavaDayTokyoでデモで使用されたファイルです。
/*

 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.

 *

 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.

 *

 * The contents of this file are subject to the terms of either the GNU

 * General Public License Version 2 only ("GPL") or the Common Development

 * and Distribution License("CDDL") (collectively, the "License").  You

 * may not use this file except in compliance with the License.  You can

 * obtain a copy of the License at

 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html

 * or packager/legal/LICENSE.txt.  See the License for the specific

 * language governing permissions and limitations under the License.

 *

 * When distributing the software, include this License Header Notice in each

 * file and include the License file at packager/legal/LICENSE.txt.

 *

 * GPL Classpath Exception:

 * Oracle designates this particular file as subject to the "Classpath"

 * exception as provided by Oracle in the GPL Version 2 section of the License

 * file that accompanied this code.

 *

 * Modifications:

 * If applicable, add the following below the License Header, with the fields

 * enclosed by brackets [] replaced by your own identifying information:

 * "Portions Copyright [year] [name of copyright owner]"

 *

 * Contributor(s):

 * If you wish your version of this file to be governed by only the CDDL or

 * only the GPL Version 2, indicate your decision by adding "[Contributor]

 * elects to include this software in this distribution under the [CDDL or GPL

 * Version 2] license."  If you don't indicate a single choice of license, a

 * recipient has the option to distribute your version of this file under

 * either the CDDL, the GPL Version 2 or to extend the choice of license to

 * its licensees as provided above.  However, if you add GPL Version 2 code

 * and therefore, elected the GPL Version 2 license, then the option applies

 * only if the new code is made subject to such option by the copyright

 * holder.

 */



var wsUri = "ws://" + document.location.host + "/Chat/websocket";

var websocket = new WebSocket(wsUri);



var username;

websocket.onopen = function(evt) { onOpen(evt) };

websocket.onmessage = function(evt) { onMessage(evt) };

websocket.onerror = function(evt) { onError(evt) };

var output = document.getElementById("output");



function join() {

    username = textField.value;

    websocket.send(username + " joined");

}



function send_message() {

    websocket.send(username + ": " + textField.value);

}



function onOpen() {

    writeToScreen("Connected to " + wsUri);

}



function onMessage(evt) {

    console.log("onMessage");

    writeToScreen("RECEIVED: " + evt.data);

    if (evt.data.indexOf("joined") != -1) {

        userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";

    } else {

        chatlogField.innerHTML += evt.data + "\n";

    }

}



function onError(evt) {

    writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);

}



function writeToScreen(message) {

    output.innerHTML += message + "<br>";

}


⑤最後にhtml index.html
※これはJavaDayTokyoでデモで使用されたファイルを参考にしています。
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>WebSocket Chat</title>
    </head>
    <body>
        <h1>Chat!</h1>
        <div style="text-align: center;">
            <form action="">

                <table>
                    <tr>
                        <td>
                            Users<br/>
                            <textarea readonly="true" rows="6" cols="20" id="userField"></textarea>
                        </td>
                        <td>
                            Chat Log<br/>
                            <textarea readonly="true" rows="6" cols="50" id="chatlogField"></textarea>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <input id="textField" name="name" value="Duke" type="text"><br>
                            <input onclick="join();" value="Join" type="button">
                            <input onclick="send_message();" value="Chat" type="button">
                        </td>
                    </tr>
                </table>

            </form>
        </div>
        <div id="output"></div>
        <script language="javascript" type="text/javascript" src="websocket.js">

        </script>

    </body>
</html>


⑤完成です

これだけではwebsocketの威力は感じにくいかもしれません。
このチャットアプリを少し応用して複数の人が1つのcanvasに絵が書けるアプリを作ってみました。
とても簡単に作る事ができ、websocketの威力を味わえた気がします。


0 件のコメント:

コメントを投稿