Real Time Web Application with Netty-SocketIO
Posted: March 20, 2015 Filed under: Java | Tags: java, Netty-SocketIO, SocketIO 2 CommentsWeb browser communications protocol is limited to the HTTP request and response paradigm – i.e. the browser requests and the server responds. For real time web application we want to perform duplex communication – i.e. where the server sends a request and the browser responds and the vice versa. There are variety of transport options to achieve this like WebSocket, XHR polling, etc.
Socket.IO is a JavaScript library that uses a variety of transport (WebSocket, XHR polling, etc) to allow you to develop real-time web application. Socket.IO hides the underlying transport mechanism by figuring out what is the best transport to use between the browser and the server. It performs a handshake to determine this. Most Socket.IO servers are written in JavaScript running in node.js.
We can integrate a Socket.IO client to Java EE 7 using the new WebSocket API (JSR-356). It provides bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket. In addition, because WebSockets can co-exist with other HTTP traffic over port 80 and 443, firewalls will not have to be re-configured.
Mainly there are two server side Java implementation of Socket.IO. They are Netty-SocketIO and Socket.IO-Java. Socket.IO-Java is a J2EE Servlet based Socket.IO server implementation and runs on top of Jetty leveraging its WebSocket and continuation support. Netty-SocketIO is based on Red Hat’s Netty(a non-blocking I/O (NIO) client-server framework). It supports latest protocol of Socket.IO server.
We could get the Netty-SocketIO library here. And you could familiarize the API by just running this demo.
Lately I have integrated Netty-SocketIO into my servlet. You could find the code below. All you have to do is start your SocektServerIO in servlet init method in port 80 or 443.
HelloWorld.java – Servlet
package com.vaisakh.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.corundumstudio.socketio.*; import com.corundumstudio.socketio.listener.DataListener; @WebServlet("/HelloWorld") public class HelloWorld extends HttpServlet { private static final long serialVersionUID = 1L; SocketIOServer socketIOServer = null; public HelloWorld() { super(); } public void init(ServletConfig config) throws ServletException { Configuration configuration = new Configuration(); configuration.setHostname("localhost"); configuration.setPort(80); socketIOServer = new SocketIOServer(configuration); socketIOServer.addEventListener("chatevent", ChatObject.class, new DataListener<ChatObject>() { @Override public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) throws Exception { socketIOServer.getBroadcastOperations().sendEvent("chatevent", data); } }); socketIOServer.start(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/home.jsp").forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } public void destroy() { socketIOServer.stop(); } }
ChatObject.java – Model class
package com.vaisakh.servlet; public class ChatObject { private String userName; private String message; public ChatObject() { super(); } public ChatObject(String userName, String message) { super(); this.userName = userName; this.message = message; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
home.jsp – View
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Chat App</title> <link href="bootstrap.css" rel="stylesheet"> <style type="text/css"> body { padding: 20px; } #console { height: 400px; overflow: auto; } .username-msg { color: orange; } .connect-msg { color: green; } .disconnect-msg { color: red; } .send-msg { color: #888 } </style> <script type="text/javascript" src="js/socket.io/socket.io.js"></script> <script type="text/javascript" src="js/moment.min.js"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script type="text/javascript"> var userName = 'user' + Math.floor((Math.random() * 1000) + 1); var socket = io.connect('http://localhost:80'); socket .on( 'connect', function() { output('<span class="connect-msg">Client has connected to the server!</span>'); }); socket.on('chatevent', function(data) { output('<span class="username-msg">' + data.userName + ':</span> ' + data.message); }); socket.on('disconnect', function() { output('<span class="disconnect-msg">The Client(' + userName + ') has disconnected!</span>'); }); function sendDisconnect() { socket.disconnect(); } function sendMessage() { var message = $('#msg').val(); $('#msg').val(' '); var jsonObject = { userName : userName, message : message }; socket.emit('chatevent', jsonObject); } function output(message) { var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>"; var element = $("<div>" + currentTime + " " + message + "</div>"); $('#console').prepend(element); } </script> </head> <body> <h1>My Chat App</h1> <br /> <div id="console" class="well"></div> <form class="well form-inline" onsubmit="return false;"> <input id="msg" class="input-xlarge" type="text"/> <button type="button" onClick="sendMessage()" class="btn">Send</button> <button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button> </form> </body> </html>
You need to add Netty-SocketIO library to class path. Also the javascript libraries refereed in the view