WebSocketでEchoServerをつくる(Tomcat7編)

Tomcatもバージョン7からWebSocketに対応しているらしい。
そんなわけで、前回はJetty8を使ったが、今回はTomcat7でEchoServerをつくってみる。

なお、TomcatドキュメントのWebSocketのところを見ると「まだ開発終わってないよ」と書かれているが、お試しなので気にしないことにする。

今回、使ったのは以下。

サーバ:Tomcat 7.0.34
クライアント:Google Chrome 24.0.1312.52

で、サーバ側のソースコード

package test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
import org.apache.log4j.Logger;

@WebServlet("/EchoServlet")
public class EchoServlet extends WebSocketServlet {
	private static final long serialVersionUID = 1L;
	private static final Logger logger = Logger.getLogger(EchoServlet.class);
       
	@Override
	protected StreamInbound createWebSocketInbound(String subProtocol,
			HttpServletRequest request) {
		return new EchoStreamInbound();
	}

	class EchoStreamInbound extends MessageInbound {
		private WsOutbound wsb;

		@Override
		protected void onOpen(WsOutbound outbound) {
			logger.info("Open");
			wsb = outbound;
		}
		
		@Override
		protected void onClose(int status) {
			logger.info("Close");
		}
		
		@Override
		protected void onBinaryMessage(ByteBuffer message) throws IOException {
			// バイナリデータの場合は何もしない
		}

		@Override
		protected void onTextMessage(CharBuffer message) throws IOException {
			logger.info("received:" + message.toString());
			wsb.writeTextMessage(message);
		}
		
	}
}

継承する親クラスの名前はWebSocketServletでJettyの場合と同じだが、オーバーライドするメソッドは当然異なる。
下のクライアント側のHTMLは前回とほとんど同じで、接続先のURLだけ変えてある。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Test</title>
</head>
<body>
	<div id="status">ステータス:未接続</div>
	<input type="text" id="msg">
	<button onclick="sendMessage()">send</button>
	<br>
	<textarea id="data" rows="10" cols="50" readonly></textarea>
	<br>
	<button onclick="closeConnection()">close</button>

	<script type="text/javascript">
		var con_status = document.getElementById("status")
		var msg = document.getElementById("msg");
		var data = document.getElementById("data");
		var ws = new WebSocket("ws://localhost:8080/WebSocket_Tomcat/EchoServlet");

		ws.onopen = function(e) {
			con_status.textContent = "ステータス:接続済み";
		}

		ws.onmessage = function(e) {
			var message = e.data;
			data.textContent += message + "\n";
		}

		ws.onclose = function(e) {
			con_status.textContent = "ステータス:未接続";
		}

		function sendMessage() {
			ws.send(msg.value);
			msg.value = "";
		}

		function closeConnection() {
			ws.close();
		}
	</script>
</body>
</html>

今回も無事に動いた。