WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection. It is designed to be implemented in web browsers and web servers, but it can be used by any client or server application.
Protocol
To establish a WebSocket connection, the client sends a WebSocket handshake request, for which the server returns a WebSocket handshake response, as shown in the example below.
1 | GET /chat HTTP/1.1 |
Server response:
1 | HTTP/1.1 101 Switching Protocols |
Notes:
The “upgrade header(the “Upgrade”/“Connection” items) is used in the request/response to set up a connection;
The HTTP status code “101 Switching Protocols” is used in the response;
The client sends a “Sec-WebSocket-Key” header containing base64-encoded random bytes, and the server replies with a hash of the key in the “Sec-WebSocket-Accept” header. The hashing function appends the fixed string “258EAFA5-E914-47DA-95CA-C5AB0DC85B11“ (a GUID) to the value from “Sec-WebSocket-Key” header (which is not decoded from base64), applies the SHA-1 hashing function, and encodes the result using base64(from here). This logic can be verified by the following commands with the example values in the above request/response:
1 | # The "-n" argument of "echo" removes the trailing newline: |
Server Side
In the Java world, you can use “Tyrus“ to implement the WebSocket server side. The offical document has detail description about how to do it.
If you are adding WebSocket feature in your WAR project, add the following dependencies in your “pom.xml”:
1 | <dependency> |
This is used to import the annotations below to create the WebSocket server side code. Since “JSR 356, Java API for WebSocket” is part of Java EE 7, any application server supports Java EE 7 should already have this dependency. For web containers, Tomcat supports the Java WebSocket 1.1 API defined by JSR-356 from version 7.0. So I speculate in a war deployed in such environment, marking the dependency as “<scope>provided</scope>” is enough.
Then you need to create a Java class with the annotations which aims to handle the WebSocket request as the WebSocket server side(from here):
1 | import java.io.IOException; |
Note the “javax.websocket.*“ annotations which are used to mark the Java class as WebSocket server side implementation.
Besides the annotation implementation, another “MessageHandlers” programmatic endpoint implementation can by used:
1 | import javax.websocket.Endpoint; |
From here: Deploying WebSocket endpoints can be done in two ways. Either deploying via putting the endpoint in the WAR file, or using the ServerContainer methods to deploy the programmatic endpoint in the deployment phase.
For deploying Endpoints as a WAR file:
The classes that are scanned for in WAR are the following ones:
Classes that implement the javax.websocket.ServerApplicationConfig.
Classes annotated with javax.websocket.server.ServerEndpoint.
Classes that extend javax.websocket.Endpoint.
More details can be found from the official document. This way is easy and I think it’s the way that most developers do.
Deploying endpoints via “javax.websocket.server.ServerContainer”
Endpoints may be deployed using javax.websocket.server.ServerContainer during the application initialization phase. For websocket enabled web containers, developers may obtain a reference to the ServerContainer instance by retrieving it as an attribute named javax.websocket.server.ServerContainer on the ServletContext, see the following example for annotated endpoint:
1 | import javax.servlet.ServletContextEvent; |
Client Side
It seems there are many ways to implement the client side such as using “Angular Websocket“:
1 | <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> |
Finally, here is a very good article about this topic: “Java EE 7 and WebSocket API for Java (JSR 356) with AngularJS on WildFly“.