From ed65dffddf2f4060d7a009f22b15c3d21e4e1b3c Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Sun, 25 Nov 2012 14:09:51 +0100 Subject: [PATCH] Adding WebSocket Example using WebSocketServerProtocolHandler. --- .../html5/CustomTextFrameHandler.java | 33 ++++++++ .../websocketx/html5/WebSocketServer.java | 79 +++++++++++++++++++ .../html5/WebSocketServerPipelineFactory.java | 38 +++++++++ .../resources/websocketx/html5/css/socket.css | 4 + .../resources/websocketx/html5/js/socket.js | 53 +++++++++++++ .../resources/websocketx/html5/websocket.html | 18 +++++ 6 files changed, 225 insertions(+) create mode 100644 src/main/java/org/jboss/netty/example/http/websocketx/html5/CustomTextFrameHandler.java create mode 100644 src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServer.java create mode 100644 src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServerPipelineFactory.java create mode 100644 src/test/resources/websocketx/html5/css/socket.css create mode 100644 src/test/resources/websocketx/html5/js/socket.js create mode 100644 src/test/resources/websocketx/html5/websocket.html diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/html5/CustomTextFrameHandler.java b/src/main/java/org/jboss/netty/example/http/websocketx/html5/CustomTextFrameHandler.java new file mode 100644 index 0000000000..468f1d2a9f --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/websocketx/html5/CustomTextFrameHandler.java @@ -0,0 +1,33 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.jboss.netty.example.http.websocketx.html5; + +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +public class CustomTextFrameHandler extends SimpleChannelHandler { + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + if (e.getMessage() instanceof TextWebSocketFrame) { + TextWebSocketFrame frame = (TextWebSocketFrame) e.getMessage(); + ctx.getChannel().write(new TextWebSocketFrame(frame.getText().toUpperCase())); + } + } + +} diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServer.java b/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServer.java new file mode 100644 index 0000000000..ab1023768a --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.jboss.netty.example.http.websocketx.html5; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; +import org.jboss.netty.example.http.websocketx.server.WebSocketServerPipelineFactory; + +/** + * A WebSocket Server that respondes to requests at: + * + *
+ * http://localhost:8080/websocket
+ * 
+ * + * The example differs from many of the other examples in Netty in that is does + * not have an acomponying client. Instead a html page is provided that + * interacts with this server.
+ * Open up the following file a web browser that supports WebSocket's: + * + *
+ * netty/src/test/resources/websocketx/html5/websocket.html
+ * 
+ * + * The html page is very simple were you simply enter some text and the server + * will echo the same text back, but in uppercase. You, also see status messages + * in the "Response From Server" area when client has connected, disconnected + * etc. + * + */ +public class WebSocketServer { + + private final int port; + + public WebSocketServer(int port) { + this.port = port; + } + + public void run() { + // Configure the server. + ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); + + // Set up the event pipeline factory. + bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory()); + + // Bind and start to accept incoming connections. + bootstrap.bind(new InetSocketAddress(port)); + + System.out.println("Web socket server started at port " + port + '.'); + } + + public static void main(String[] args) { + int port; + if (args.length > 0) { + port = Integer.parseInt(args[0]); + } else { + port = 8080; + } + new WebSocketServer(port).run(); + } + +} diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServerPipelineFactory.java b/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServerPipelineFactory.java new file mode 100644 index 0000000000..406fa9bd2d --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/websocketx/html5/WebSocketServerPipelineFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package org.jboss.netty.example.http.websocketx.html5; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.http.HttpChunkAggregator; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; +import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; + +public class WebSocketServerPipelineFactory implements ChannelPipelineFactory { + public ChannelPipeline getPipeline() throws Exception { + // Create a default pipeline implementation. + ChannelPipeline pipeline = pipeline(); + pipeline.addLast("decoder", new HttpRequestDecoder()); + pipeline.addLast("aggregator", new HttpChunkAggregator(65536)); + pipeline.addLast("encoder", new HttpResponseEncoder()); + pipeline.addLast("handler", new WebSocketServerProtocolHandler("/websocket")); + pipeline.addLast("testFramehandler", new CustomTextFrameHandler()); + return pipeline; + } +} diff --git a/src/test/resources/websocketx/html5/css/socket.css b/src/test/resources/websocketx/html5/css/socket.css new file mode 100644 index 0000000000..c50fdef00e --- /dev/null +++ b/src/test/resources/websocketx/html5/css/socket.css @@ -0,0 +1,4 @@ +textarea { + width: 500px; + height: 300px; +} \ No newline at end of file diff --git a/src/test/resources/websocketx/html5/js/socket.js b/src/test/resources/websocketx/html5/js/socket.js new file mode 100644 index 0000000000..0abc6d8200 --- /dev/null +++ b/src/test/resources/websocketx/html5/js/socket.js @@ -0,0 +1,53 @@ +(function() { + var Sock = function() { + var socket; + if (!window.WebSocket) { + window.WebSocket = window.MozWebSocket; + } + + if (window.WebSocket) { + socket = new WebSocket("ws://localhost:8080/websocket"); + socket.onopen = onopen; + socket.onmessage = onmessage; + socket.onclose = onclose; + } else { + alert("Your browser does not support Web Socket."); + } + + function onopen(event) { + getTextAreaElement().value = "Web Socket opened!"; + } + + function onmessage(event) { + appendTextArea(event.data); + } + + function onclose(event) { + appendTextArea("Web Socket closed"); + } + + function appendTextArea(newData) { + var el = getTextAreaElement(); + el.value = el.value + '\n' + newData; + } + + function getTextAreaElement() { + return document.getElementById('responseText'); + } + + function send(e) { + e.preventDefault(); + if (window.WebSocket) { + if (socket.readyState == WebSocket.OPEN) { + socket.send(event.target.message.value); + } else { + alert("The socket is not open."); + } + } + } + document.forms.inputform.addEventListener('submit', send, false); + } + window.addEventListener('load', function() { + new Sock(); + }, false); +})(); diff --git a/src/test/resources/websocketx/html5/websocket.html b/src/test/resources/websocketx/html5/websocket.html new file mode 100644 index 0000000000..f80d25a22c --- /dev/null +++ b/src/test/resources/websocketx/html5/websocket.html @@ -0,0 +1,18 @@ + + + + + Web Socket Example + + + + +

Enter a message

+
+ + +
+

Repsonse from Server

+ + +