1. A brief introduction to WebSocket
With the development of the Internet, traditional HTTP protocols have been difficult to meet the increasingly complex needs of Web applications. In recent years, with the birth of HTML5, the WebSocket protocol has been proposed. It realizes full-duplex communication between the browser and the server, expands the communication function between the browser and the server, and enables the server to actively send data to the client.
We know that the traditional HTTP protocol is stateless. Each request must be initiated by the client (such as a browser). After processing, the server returns the response result. It is difficult for the server to actively send data to the client. This kind of client is the active party and the server is the passive party. The traditional web model causes less trouble for web applications with infrequent information changes, but it brings great inconvenience to web applications involving real-time information, such as applications with functions such as instant communication, real-time data, subscription push, etc. Before the WebSocket specification was proposed, developers often use trade-off solutions to implement these highly real-time functions: polling and Comet technologies. In fact, the latter is essentially a kind of polling, but it has been improved.
Polling is the most original solution to implement real-time web applications. Polling technology requires clients to periodically send requests to the server at a set time interval and frequently query whether there are new data changes. Obviously, this approach can lead to too many unnecessary requests, wasting traffic and server resources.
Comet technology can be divided into long polling and streaming technology. Long polling improves the above-mentioned polling technology, reducing useless requests. It sets an expiration time for certain data, and only sends a request to the server after the data expires; this mechanism is suitable for situations where data changes are not particularly frequent. Streaming technology usually refers to the client using a hidden window to establish an HTTP long connection with the server. The server will constantly update the connection status to keep the HTTP long connection alive; in this way, the server can actively send data to the client through this long connection; streaming technology may test the performance of the server in a large concurrency environment.
Both technologies are based on the request-response mode and are not considered real-time technologies in the true sense; each request or response of their wastes a certain amount of traffic on the same header information, and the development complexity is also high.
With the launch of HTML5, WebSocket truly realizes real-time communication of the web, making the B/S mode have the real-time communication capabilities of C/S mode. The workflow of WebSocket is as follows: the browser sends a request to the server to establish a WebSocket connection through JavaScript. After the WebSocket connection is successfully established, the client and the server can transmit data through the TCP connection. Because WebSocket connection is essentially a TCP connection, it does not require repeated header data to be carried with each transmission, so its data transmission volume is much smaller than polling and Comet technology. This article does not introduce the WebSocket specification in detail, but mainly introduces the implementation of WebSocket in Java Web.
JavaEE 7 has created JSR-356:Java API for WebSocket specification. Many web containers, such as Tomcat, Nginx, Jetty, etc., support WebSocket. Tomcat supports WebSocket since 7.0.27 and JSR-356 since 7.0.47. The following demo code also needs to be deployed on Tomcat7.0.47 or above to run.
Client (Web homepage) code:
<%@ page language="java" pageEncoding="UTF-8" %><!DOCTYPE html><html><head> <title>Tomcat implementation of Java backend WebSocket</title></head><body> Welcome<br/><input id="text" type="text"/> <button onclick="send()">Send a message</button> <hr/> <button onclick="closeWebSocket()">Close WebSocket connection</button> <hr/> <div id="message"></div></body><script type="text/javascript"> var websocket = null; //Judge whether the current browser supports WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://172.16.98.31:8080/websocket/websocket"); } else { alert('Current browser Not support websocket'); } //Callback method for errors in connection websocket.onerror = function () { setMessageInnerHTML("Error in WebSocket connection"); }; //Callback method for successful connection websocket.onopen = function () { setMessageInnerHTML("WebSocket connection successful"); } //Callback method of receiving the message websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //Callback method of connection closing websocket.onclose = function () { setMessageInnerHTML("WebSocket connection closed"); } // Listen to the window closing event. When the window is closed, actively close the websocket connection to prevent the window from closing before the connection is disconnected, and the server side will throw exceptions. window.onbeforeunload = function () { closeWebSocket(); } //Show the message on the web page function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //Close WebSocket connection function closeWebSocket() { websocket.close(); } //Send message function send() { var message = document.getElementById('text').value; websocket.send(message); }</script></html> Java Web Backend Code
package cn.com;import java.io.IOException;import java.util.concurrent.CopyOnWriteArraySet;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;/** * @ServerEndpoint Annotation is a class-level annotation. Its function is mainly to define the current class as a websocket server side. * The annotation value will be used to listen to the user's connection to the terminal access URL address. The client can connect to the WebSocket server side through this URL* Every time a request is made, an instance will be created*/@ServerEndpoint("/websocket")public class WebSocketTest { // Static variables are used to record the current number of online connections. It should be designed to be thread-safe. private static int onlineCount = 0; //The thread-safe Set of the concurrent package is used to store the corresponding MyWebSocket object of each client. To realize that the server communicates with a single client, you can use Map to store it, where the Key can identify the user private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>(); //The connection session with a certain client needs to send data to the client through it private Session session; /** * Method for successfully calling connection establishment* @param session Optional parameter. session is a connection session with a client, and it needs to send data to the client through it*/ @OnOpen public void onOpen(Session session){ this.session = session; webSocketSet.add(this); //Add to addOnlineCount() in set; //Add 1 online number System.out.println("There is a new connection to join! The current number of online people is" + getOnlineCount()); } /** * Method for connecting closing calls*/ @OnClose public void onClose(){ webSocketSet.remove(this); //Delete subOnlineCount() from set; //Delete online number by 1 online number System.out.println("There is a connection closed! The current number of people online is" + getOnlineCount()); } /** * Method called after receiving the client message* @param message The message sent by the client* @param session Optional parameter*/ @OnMessage public void onMessage(String message, Session session) { System.out.println("Message from the client:" + message); //Batch message for(WebSocketTest item: webSocketSet){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } } /** * Called when an error occurs * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("Error occurred"); error.printStackTrace(); } /** * This method is different from the above methods. There is no annotation, it is a method added according to your needs. * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketTest.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketTest.onlineCount--; }}Open two browsers, enter the URL, and run it directly
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.