WeSocket enables instant messaging

catalogue

1, websocket Technology

1. Application scenario of websocket Technology

2. Overview of websocket protocol

3. Difference between full duplex and simplex

4. Push technology and pull technology (understand)

5. Internet technology

 

6. Advantages of Wenbsocket

2, SpringBoot uses WebSocket to implement chat room

1. Structure diagram of implementation

2. Message format

3. Function realization

1. Create a project and import the coordinates of relevant jar packages

2. Creating public resources

3. Realization of login function

4. Implementation of configuration class

5. Build a server class

6,GetHttpSessionConfigurator

 

 

1, websocket Technology

1. Application scenario of websocket Technology

Use java technology to quickly learn a simple online chat room system. The system has strong expansibility. According to business needs, it can make online customer service system, web version of wechat, QQ instant messaging system, etc., use more popular technology and adopt building block programming ideas.

The real-time push technology in the web field is also called Realtime technology. The purpose of this technology is to bypass the user and obtain real-time updates without refreshing the browser. It has a wide range of application prospects, such as online chat room, online customer service system, comment system, WebIM and so on.

 

2. Overview of websocket protocol

webSocket protocol is a new protocol of HTML5. He realized full duplex communication between browser and server. The initial handshake needs to be completed with the help of HTTP request.

websocket is an Internet technology that realizes the full duplex communication from server to client.

It is a protocol for full duplex communication over a single TCP connection. webSocket communication protocol was defined as standard RFC 6455 by IETF in 2011, and webSocket API was defined as standard by W3c.

 

3. Difference between full duplex and simplex

 

  • Full duplex: a term for communication transmission. Communication allows data to be transmitted simultaneously in two directions. Its capability is equivalent to the combination of two simplex communication modes. Full duplex refers to the two-way transmission of signals simultaneously (instantaneously) (a - > b, B-A) refers to the simultaneous synchronization of a - > b and B - > a.

 

  • Simplex and half duplex. The so-called half duplex means that only one action occurs in a time period. For example, only one carriage can pass through a narrow road at the same time. When there are two carriages at present, one needs to wait for the other to pass. This example vividly illustrates the principle of half duplex. Early walkie talkies and early hubs were based on half duplex products. With the continuous progress of technology, semi double trade unions gradually withdrew from the historical stage

 

4. Push technology and pull technology (understand)

 

  • Push technology is a mechanism established on the client server, which is the technology that the server actively sends information to the client, just like broadcasting by a radio station.
  • Compared with the traditional pull Pull technology, the main difference is that the push Push technology is the simultaneous interpreting of the information from the server to the client, while the pull PULL technology is the client's active request for information. The advantage of push technology lies in the initiative and timeliness of information.
  • In short, compared with the server, the pull technology is to passively provide data to the client, and the push technology is to actively provide data to the client

5. Internet technology

 

Definition of Internet technology: Internet technology refers to an information technology developed and established on the basis of computer technology; Abbreviation: IT

This technology integrates the scattered resources on the Internet into an organic whole, realizes the comprehensive sharing and organic cooperation of resources, and enables people to use the overall ability of resources transparently and obtain information on demand.

 

6. Advantages of Wenbsocket

 

In the past, no matter using HTTP polling or using TCP long connection to make online chat system, it has natural defects. With the development of Html5, there is a new protocol Websocket protocol, which can realize full duplex communication between browser and server. It can do: browser and server only need one handshake, and then, A fast track is formed between the browser and the server. Data can be transmitted between the two. The characteristics of this new protocol are just suitable for this kind of online instant messaging.

Implementation of traditional Http protocol:

The http protocol can request multiple times, because the connection will be closed after each request. The next time you re request data, you need to open the connection again

 

Traditional Socket technology:

 

Long connection

Client - connect first - server

Benefits: it can realize two-way communication between client and server

Disadvantages: if everyone doesn't speak, it will cause a waste of resources

 

 

Other features include:

 

(1) Based on TCP protocol, the server-side implementation is relatively easy.

(2) It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase adopts HTTP protocol, so it is not easy to shield the handshake and can pass through various HTTP proxy servers.

(3) The data format is light, the performance overhead is small, and the communication is efficient.

(4) You can send text or binary data.

(5) There is no homology restriction, and the client can communicate with any server.

(6) The protocol identifier is ws (wss if encrypted), and the server URL is the URL.

        ws://example.com:80/some/path

 

 

2, SpringBoot uses WebSocket to implement chat room

 

1. Structure diagram of implementation

2. Message format

 

  • Client -------- server
{"toName":"Zhang San","message":"Hello"}

toName:To whom message:Message content sent

 

  • Server ----- client
System message format:

{"isSystem":true,"fromName":null,"message":["Li Si","Wang Wu"]}

isSystem:Is it a system message

fromName:Who sent it

message: Message content sent

Chat message format:

{"isSystem":true,"formName:"Zhang San","message":"Hello"}

 

3. Function realization

 

1. Create a project and import the coordinates of relevant jar packages

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>

</dependency>
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

 

2. Create public resources

 

Message class: used for the webSocket data sent by the browser to the server

package com.pojo;

import lombok.Data;

//Used to send data from the browser to the server
@Data
public class Message {
    private  String toName;
    private  String message;
}

 

ResultMessage: used for the server to send the browser's Websocket data

package com.pojo;

import lombok.Data;
//Websocket data for the server to send the browser
@Data
public class ResultMessage {
    private boolean isSystem;//Is it a system message
    private String  fromName;
    private Object message; //If it is a system message, it is an array
}

 

MessageUtils: tool class used to encapsulate messages

The data needs to be converted into a format recognized by Websocket

package com.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pojo.ResultMessage;

//Tool class used to encapsulate messages
public class MessageUtils {
    public static String getMesssge(boolean isSystemMessage,String fromName,Object message){
        try {
            ResultMessage result = new ResultMessage();
            result.setSystem(isSystemMessage);
            result.setMessage(message);
            if(fromName!=null){
                result.setFromName(fromName);
            }
            ObjectMapper mapper=new ObjectMapper();
            return  mapper.writeValueAsString(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null;
    }
}

 

result: data used to log in and respond to the browser

package com.pojo;

import lombok.Data;

//Data used to respond to the browser after login
@Data
public class Result {
    private  boolean flag;
    private  String  message;
}

 

3. Realization of login function

 

  • login.html: sending requests using asynchrony
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<form id="loginForm">
    <input type="text" placeholder="Please enter your name..." name="username"/>
    <input type="password" name="password"/>
    <input type="button" id="btn"/>
</form>
</body>
<script>
    $(function () {
        $("#btn").click(function () {
        $.get("login",$("#loginForm").serialize(),function (res) {
            if (res.flag){
                //Jump to main HTML page
                location.href="main.html";
            }else {
                $("#err_msg").html(res.message);
            }
        },"json");
        });
    })
</script>
</html>
  • userController: login logic processing
package com.controller;

import com.pojo.Result;
import com.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

//userController: login logic processing
@RestController
public class UserController {
    @RequestMapping("/login")
    public Result login(User user, HttpSession session){
        Result result = new Result();
        if(user!=null&&"123".equals(user.getPassword())){
            result.setFlag(true);
            //Save user to session object
            session.setAttribute("user",user.getUsername());
        }else {
            result.setFlag(false);
            result.setMessage("Login failed");
        }
        return  result;
    }
    
    @RequestMapping("/getUsername")
    public  String getUsername(HttpSession session){
    String username = (String) session.getAttribute("user");
    return username;
    }
}   

 

  • main.html: the page of chat function
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<div>
    <div>
        <div>
            <!--            <div id="username"></span></div>   User: Zhang San<span style="float: right;color: green">on-line-->
            <div id="username"></span></div>
            <div id="chatMes">
                <!--And<font face=""Italics">Zhang San</font>chat-->
            </div>
        </div>
        <!--Chat area start-->
        <div id="pnlBody">
            <div id="initBackground" style="background-color: white;width: 100%">
                <div id="chatArea" style="display: none">
                    <div id="show">
                        <div id="hists"></div>
                        <div id="msgs">
                            <!--Message display area-->
                            <div class="msg guest">
                                <div class="msg-right">
                                    <div>Hello</div>
                                </div>
                            </div>
                            <div class="msg robot">
                                <div class="msg-left">
                                    <div>Hello</div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div>
                        <div>
                            <textarea id="context_text" wrap="hard" placeholder="Enter text here..."></textarea>
                            <div id="atcomPnl">
                                <ul id="atcom"></ul>
                            </div>
                        </div>
                        <div id="submit">
                            send out
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <!--End of chat area-->
        <div>
            <div></div>
            <div>
                <div>
                    <div id="hot-tab">Friends list</div>
                </div>
                <div>
                    <ul id="userList">

                    </ul>
                </div>
            </div>
            <div>
                <div>
                    <div>System broadcast</div>
                </div>
                <div>
                    <ul id="broadcastList">

                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    var username;
    var toName;

    function showChat(name) {
        toName = name;
        //Now chat dialog
        $("#chatArea").css("display", "inline");
        //Clear chat dialog
        $("#msgs").html("");
        //Show who you are chatting with“
        $("#chatMes").html(" chatting with < font face = \ "italics \" > "+ toname +" < font > ");

        //sessionStorage
        var chatData= sessionStorage.getItem(toName);
        if(chatData!=null){
            //Render chat records to chat area
            $("#msgs").html(chatData);
        }

    }


    $(function () {
        $.ajax({
            url: "getUsername",
            success: function (res) {

                username = res;
                //Display online information
                $("#username").html(" user: "+ res +" < span style ='float: right; color: Green '> online < / span > ");

            },
            async: false //Asynchronous request
        });
        //Create a webSocket object
        var ws = new WebSocket("ws://192.168.43.24:8080/chat");
        //Click time for ws binding
        ws.onopen = function () {
            //What needs to be done after the connection is established?
            //Display online information
            $("#username").html("User:" + username + "<span style='float:right;color:#008000 '> online < / span > ");

        }
        //Triggered after receiving the message pushed by the server
        ws.onmessage = function (evt) {
            //Get messages pushed by the server
            var dataStr = evt.data;
            //Convert dataStr to Json object
            var res = JSON.parse(dataStr);
            console.log(res);
            console.log(res.message);
            //Determine whether it is a system message
            if (res.system) {
                var names = res.message;
                //System message
                //1. Friends list display
                var userlistStr = "";
                var broadcastListStr = "";
                for (var name of names) {
                    if (name != username) {
                        userlistStr += "<li class=\"rel-item\"><a onclick='showChat(\"" + name + "\")'>" + name + "</a></li>";
                        broadcastListStr += "<li class=\"rel-item\" style=\"color:#9d9d9d; Font family: Arial \ "> your friend" + name + "online < / Li >";
                     }
                }
                //Render friend list and system broadcast
                $("#userList").html(userlistStr);
                $("#broadcastList").html(broadcastListStr);
                //2. System broadcast display
            } else {
                //Not a system message
                //Display the messages pushed by the server
               // var str="<div class='\msg robot\'><div class=\"msg-left\" worker=\"\"><div class =\"msg-host photo\" style='background-image: url(img)'></div>"
                var str="<h5 style='text-align: left'>"+res.message+"</h5>";
                if(toName==res.fromName){
                    $("#msgs").append(str);
                }
                var chatData = sessionStorage.getItem(res.fromName);
                if (chatData!=null){
                    str=chatData+str;
                }
                sessionStorage.setItem(res.fromName,str);
            }

        }
        ws.onclose = function () {
            //Display offline information
            $("#username").html(" user: "+ username +" < span style ='float: right; color: Red '> offline < / span > ");

        }
        $("#submit").click(function () {
            //Get input
            var data=$("#context_text").val();
            //Clear the contents of the input area
            $("#context_text").val("");
            var json={"toName":toName,"message":data};

            //Display data in chat area
            var str="<h5 style='text-align: right'>"+data+"</h5>";
            $("#msgs").append(str);
            //Send message to server
            var chatData = sessionStorage.getItem(toName);
            if (chatData!=null){
               str=chatData+str;
            }
            sessionStorage.setItem(toName,str);
            ws.send(JSON.stringify(json));
        });
    });

</script>
</html>
  • Add a getUsername method in UserController to obtain the currently logged in user name from Session and respond back to the browser
@RequestMapping("/getUsername")
public  String getUsername(HttpSession session){
    String username = (String) session.getAttribute("user");
    return username;
}   

 

4. Implementation of configuration class

 

WebSocketConfig: inject a ServerEndpointExporter class object

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    //Inject ServerEndpointExporter bean object and automatically register @ ServerEndPoint
    public ServerEndpointExporter serverEndpointExporter(){
        return  new ServerEndpointExporter();
    }
}

 

5. Build a server class

 

ChatEndpoint: realize the main functions of chat business

package com.ws;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pojo.Message;
import com.utils.MessageUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfigurator.class)
@Component
//Each client will have a reference to this object, and each object complements each other
public class ChatEndpoint {

    //It is used to store the ChatEndpoint object corresponding to each client object
    private static Map<String, ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();

    //Declare Session capriccio, which can send messages to specified users
    private Session session;

    //Declare an HttpSession object. We previously stored the user name in the HttpSession object
    private HttpSession httpSession;

    //Called when the connection is established
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        //Assign the local session object to the member variable session
        this.session = session;
        //Get httpSession object
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;
        //Stores the current object in a container
        //Get user name from HttpSession object
        String username = (String) httpSession.getAttribute("user");
        onlineUsers.put(username, this);

        //Send the user name of the current online user to all clients
        MessageUtils.getMesssge(true, null, getNames());
        //1. Get message
        String message = MessageUtils.getMesssge(true, null, getNames());
        //2. Call methods to push system messages
        broadcastAllUsers(message);

    }

    private Set<String> getNames() {
        return onlineUsers.keySet();
    }

    private void broadcastAllUsers(String message) {
        //To push this message to all clients
        Set<String> names = onlineUsers.keySet();
        for (String name : names) {
            ChatEndpoint chatEndpoint = onlineUsers.get(name);
            try {
                chatEndpoint.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //Called when data sent by the client is received
    @OnMessage
    public void onMessage(String message, Session session) {
        //Convert message to message object
        ObjectMapper mapper = new ObjectMapper();
        try {
            Message mess = mapper.readValue(message, Message.class);
            //Get who to send the data to
            String toName=mess.getToName();
            //Get message data
            String data=mess.getMessage();
            //Get the currently logged in user
            String username= (String) httpSession.getAttribute("user");
            //Gets the data of the message format pushed to the specified user
            String resultMessage=MessageUtils.getMesssge(false,username,data);
            //send data
            onlineUsers.get(toName).session.getBasicRemote().sendText(resultMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @OnClose
    public void onClose(Session session) {
      String username= (String) httpSession.getAttribute("user");
      //Deletes the specified user from the container
        onlineUsers.remove(username);
        //Get the pushed amount message
        String messsge = MessageUtils.getMesssge(true, null, getNames());
        broadcastAllUsers(messsge);
    }
}

 

6,GetHttpSessionConfigurator

 

Store the httpSession object in the configuration object

package com.ws;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public  void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response){
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        //Store the httpSession object in the configuration object
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

 

 

Added by kam_uoc on Wed, 02 Feb 2022 05:07:20 +0200