My toolbox - chat room

Posted by makka on Wed, 20 Nov 2019 22:54:21 +0100

Technical points

  • websocket Technology

When it comes to chat rooms, the preferred technology is WebSocket, which is a single TCP Connect to full duplex Communication protocol, which is more suitable for business requirements than long connection and short connection

Personal summary: long and short connections and polling are passive on the server side, only the client can initiate the request first, and the passive type of http protocol is proposed; and the websocket server side can send multiple messages to the client

Design sketch

Chat message format
{
"toid":124,
"message":"Hello?"
}
Interactive Chat

sender

Recipient

Chat with robots

When Toid is 0, send to robot

Here we use the native websocket built directly on the spring boot. In fact, the real high concurrent and high traffic business scenario is definitely the first choice to use the netty framework.

@ServerEndpoint("/chat/{userId}")
@Component
public class WebChatServer {

    static Logger log= LoggerFactory.getLogger(WebChatServer.class);
    private static int onlineCount = 0;
    private static ConcurrentHashMap<Integer,WebChatServer> webSocketMap = new ConcurrentHashMap<>();
    private Session session;
    private int userId= 0;


    static ChatRobot chatRobot;

    public WebChatServer(){

    }


    @Autowired
    public WebChatServer(ChatRobot chatRobot){
        this.chatRobot = chatRobot;
    }


    /**
     * Method successfully called for connection establishment*/
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") int userId) {
        this.session = session;
        webSocketMap.put(userId,this);     //Join set
        addOnlineCount();           //Online data plus 1
        log.info("New users start listening:"+userId+",The current number of people online is" + getOnlineCount());
        this.userId=userId;
        try {
            sendMessage("Successful connection");
        } catch (IOException e) {
            log.error("websocket IO abnormal");
        }
    }

    /**
     * Method of connection close call
     */
    @OnClose
    public void onClose() {
        webSocketMap.remove(this);  //Remove from set
        subOnlineCount();           //Online number minus 1
        log.info("There is a connection closed! The current number of people online is" + getOnlineCount());
    }

    /**
     * Method of calling after receiving client message
     *
     * @param message Messages sent by clients*/
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        log.info("Received from user"+userId+"Information:"+message);
        try{
            //Parse message
            JSONObject jsonObject = JSONObject.parseObject(message);
            int toid = (int)jsonObject.get("toid");
            if (toid == 0){
                WebChatServer webSocketServer = webSocketMap.get(toid);
                String messageContent = jsonObject.get("message").toString();
                String chatContent = chatRobot.getChatContent(messageContent);
                sendMessage(chatContent);
                log.info("Reply message to user successfully"+userId+":"+chatContent);
            }else{
                WebChatServer webSocketServer = webSocketMap.get(toid);
                if (webSocketServer != null){
                    String messageContent = jsonObject.get("message").toString();
                    webSocketServer.sendMessage(messageContent);
                    log.info("Successfully sent message to user"+toid+":"+messageContent);
                }
            }
        }catch (Exception e){
            System.out.println(e.toString());
            sendMessage("The format of sending information is wrong. Please check and resend");
        }

    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("Error occurred");
        error.printStackTrace();
    }
    /**
     * Implement server active push
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * Group custom message
     * */
    public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
        log.info("Push message to user"+userId+",Push content:"+message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebChatServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebChatServer.onlineCount--;
    }
}

Source code: https://github.com/ChenHaoHu/tools

Topics: Session Spring Netty github