Implementation of tomcat websocket

1. The client sends a handshake packet to tell the server that it wants to upgrade to WebSocket, and does not know whether the server agrees. At this time, the server supports the WebSocket protocol, and will return a handshake packet to tell the client that there is no problem, the upgrade has been confirmed, and then a WebSocket connection is successfully established, which supports two-way communication, and uses the data frame format of the WebSocket protocol to send messages. .


The handshake process needs to be explained. In order to make the WebSocket protocol compatible with the existing HTTP protocol Web architecture, the handshake of the WebSocket protocol should be based on the HTTP protocol.

WebSocket features are as follows:

  1. Single TCP long connection, using full-duplex communication mode
  2. Transparent to proxies and firewalls
  3. No header information, the message is more clear
  4. Keep alive by ping/pong
  5. The server can actively push the message to the client, no need for the client to poll


The WebSocket object can be directly manipulated through the API in javaScript, the examples are as follows:

var ws = new WebSocket(“ws://localhost:8080”);
ws.onopen = function()// Event triggered after successful establishment
{
    console.log("Open connection");
    ws.send("ddd"); // send message
};
ws.onmessage = function(evt) { // Receive server messages
    console.log(evt.data);
};
ws.onclose = function(evt) {
    console.log("WebSocketClosed!"); // close the connection
};
ws.onerror = function(evt) {
    console.log("WebSocketError!"); // Connection exception
};
 
 

websocket request header:

It contains Upgrade:websocket to tell the server that the client wants to upgrade the protocol.

The server responds and establishes a connection

At this time, if the server supports the websocket protocol, it will send a message that agrees with the client to upgrade the protocol. Among them, "Upgrade: websocket" tells the client server to agree to the client's upgrade protocol.

Check the connection status:

You can view the current connection status through ws.readyState. The optional values ​​are as follows:

1.CONNECT(0): indicates that the connection has not been established

2. OPEN(1): The connection has been established and communication is possible

3. CLISING(2): The connection is being closed by closing the handshake

4.CLOSED(3): The connection has been closed or cannot be opened



Implementation of client-side JS:

if (!window.WebSocket && window.MozWebSocket)
	window.WebSocket=window.MozWebSocket;
if (!window.WebSocket)
	alert("No Support ");
var ws;

$(document).ready(function(){
	 $("#sendbutton").attr("disabled", false);
	 $("#sendbutton").click(sendMessage);
	startWebSocket();
})

/**
 * Send message button
 * @returns
 */
function sendMessage()
{
	var msg="wyy:"+$("#message").val();
	send(msg);
}
function send(data)
{
	console.log("Send:"+data);
	ws.send(data);
}
function startWebSocket()
{	
	ws = new WebSocket("ws://" + location.host + "/WebSocket/websocket/1");
    ws.onopen = function(){
    	console.log("success open");
        $("#sendbutton").attr("disabled", false);
    };
    //Receive back-end messages and process them
	 ws.onmessage = function(event)
	 {
		 alert("RECEIVE:"+event.data);
		 handleData(event.data);
	 };
	  ws.onclose = function(event) {
         console.log('Client notified socket has closed',event);
      };
  
}

function handleData(data)
{
   $("#msg").html(data);
	
}


Implementation of client-side JS:

if (!window.WebSocket && window.MozWebSocket)
	window.WebSocket=window.MozWebSocket;
if (!window.WebSocket)
	alert("No Support ");
var ws;

$(document).ready(function(){
	 $("#sendbutton").attr("disabled", false);
	 $("#sendbutton").click(sendMessage);
	startWebSocket();
})

/**
 * Send message button
 * @returns
 */
function sendMessage()
{
	var msg="wyy:"+$("#message").val();
	send(msg);
}
function send(data)
{
	console.log("Send:"+data);
	ws.send(data);
}
function startWebSocket()
{	
	ws = new WebSocket("ws://" + location.host + "/WebSocket/websocket/1");
    ws.onopen = function(){
    	console.log("success open");
        $("#sendbutton").attr("disabled", false);
    };
    //Receive back-end messages and process them
	 ws.onmessage = function(event)
	 {
		 alert("RECEIVE:"+event.data);
		 handleData(event.data);
	 };
	  ws.onclose = function(event) {
         console.log('Client notified socket has closed',event);
      };
  
}

function handleData(data)
{
   $("#msg").html(data);
	
}

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

/**
 * The @ServerEndpoint annotation is a class-level annotation, its function is to define the current class as a websocket server,
 * The value of the annotation will be used to access the URL address of the terminal that listens for user connections, and the client can connect to the WebSocket server through this URL
 * @ServerEndpoint can turn the current class into a websocket service class
 */
@ServerEndpoint("/websocket/{userno}")
public class WebSocketTest {
	// Static variable 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 MyWebSocket object corresponding to each client. If you want to realize the communication between the server and a single client, you can use Map to store, where Key can be the user ID
	private static ConcurrentHashMap<String, WebSocketTest> webSocketSet = new ConcurrentHashMap<String, WebSocketTest>();
	// A connection session with a client, which needs to be used to send data to the client
	private Session session;
	// The number of the person currently sending the message
	private String userno = "";

	/**
	 * The method to be called successfully when the connection is established
	 *
	 * @param session
	 * optional parameters. session is a connection session with a client, which needs to be used to send data to the client
	 */
	@OnOpen
	public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) {
		System.err.println(this);
		userno = param;// The number of the person who received the message
		this.session = session;
		webSocketSet.put(param, this);//Add to map
		addOnlineCount(); // add 1 to the online count
		System.out.println("A new connection is added! The current online number is" + getOnlineCount());
	}

	/**
	 * Method to be called when the connection is closed
	 */
	@OnClose
	public void onClose() {
		if (!userno.equals("")) {
			webSocketSet.remove(userno); // remove from set
			subOnlineCount(); // subtract 1 from the online count
			System.out.println("A connection is closed! The current online number is" + getOnlineCount());
		}
	}

	/**
	 * Method called after receiving client message
	 *
	 * @param message
	 * The message sent by the client
	 * @param session
	 * optional parameters
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		System.out.println("Message from client: " + message);
		// session.get
		// group message
		sendAll(message);
	}

	/**
	 * Sending a message to the specified person can call this method directly in the project
	 *
	 * @param message
	 */
	private void sendToUser(String message) {
		// Push the message to the specified person. Before pushing the message, you must know the userno
		String now = getNowTime();
		try {
			if (webSocketSet.get(1) != null) {
				webSocketSet.get(1).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + message);
			} else {
				System.out.println("The current user is not online");
			}
		} catch (IOException e) {
			e.printStackTrace ();
		}
	}

	/**
	 * message everyone
	 *
	 * @param message
	 */
	private void sendAll(String message) {
		String now = getNowTime();
		String sendMessage = message.split("[|]")[0];
		// Traverse HashMap
		for (String key : webSocketSet.keySet()) {
			try {
				// Determine whether the receiving user is the current user who sent the message
				if (!userno.equals(key)) {
					webSocketSet.get(key).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + sendMessage);
					System.out.println("key = " + key);
				}
			} catch (IOException e) {
				e.printStackTrace ();
			}
		}
	}

	/**
	 * Get current time
	 *
	 * @return
	 */
	private String getNowTime() {
		Date date = new Date();
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = format.format(date);
		return time;
	}

	/**
	 * 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. No annotations are used, it is a method to be added according to your own 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--;
	}

}




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324643425&siteId=291194637