Building a simple HTML5 chat room

Time:2020-7-7

The front words


A web im conforming to XMPP protocol was written before, but jsjac was used, and jabber client was used in the background. It is found that nodejs event mode is more suitable for web IM client.

The traditional Ajax polling mechanism will be replaced by full duplex websocket sooner or later, so I plan to use websocket in the web IM platform of my graduation project.

In this survey and made a simple forum demo, here to talk about the implementation of this simple demo

WebSocket


What is websocket?

The protocol of websocket has not been studied carefully at present. I have time to study it

according to WebSocket.org On the definition of:

The WebSocket specification—developed as part of the HTML5 initiative— introduced the WebSocket JavaScript interface, which defines a full-duplex single socket connection over which messages can be sent between client and server. The WebSocket standard simplifies much of the complexity around bi-directional web communication and connection management.

As mentioned above, websocket defines a full duplex single socket connection between the browser and the server.

Websocket API?

The WS API of W3C defines the specific WS interface. Generally, you just need to pay attention to how to use it. You can clearly see several events of the WS client:

  1. Onopen calls after successful connection between WS client and WS server.
  2. Onmessage is called when the WS server sends data to the WS client
  3. If the connection fails, the sending or receiving data fails, or the data processing error occurs, it will be called
  4. Onclose is called when the WS client receives a WS server shutdown

Implementation of websocket server


Nodejs has a lot of websocket’s three-party libraries, which are very practical. Some people asked which library should be used in stack overflow, and the respondents gave a more comprehensive answer

Here, we make a comparison of each websocket library, which can be selected according to your own needs.

You can pay attention to it socket.io It has good support for different browsers. When websocket is not supported, it can be replaced by Ajax polling and other alternatives. The browser support is also quite good. At the same time, it can be combined with express, which is a popular web framework of node, and its document examples are well written.

Because I just want to build a simple and fast WS server, I chose the so-called “probably the fast websocket library for” node.js Ws of

Install with NPM in the project:

 npm install ws

If you need to use a simple WS client from the command line, you can:

npm install ws -g

Create a WS server:

var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({
    port: process.env.WSPORT || 3001
});

In this way, WSS becomes a WS server monitoring port 3001. We need to create events for WS server when connecting with WS client:

wss.on('connection', function(ws) {});

In this way, this event will be triggered when a WS client connects to our WS server. However, we still need to pass information after the connection, so we need to enrich the callback function of this event.

The callback function has a parameter WS, which is in charge of the connection with the WS client, and its event is the same as that of the WS client, but onopen is not required. Message and close need to be bound

wss.on('connection', function(ws) {
    ws.on('message', function(data) {

    });
    ws.on('close', function() {

    });
});

The message event is called when the WS client sends data to the WS server. The data is the data, usually of string type

The close event is called when the WS client sends a close request to the WS server

For a simple chat room, when a user joins in, it needs to tell all other users that there is a new user joining, that is, a broadcast method is required. We can define the broadcast method according to the WS example

wss.broadcast = function(data) {
    for (var i in this.clients) this.clients[i].send(JSON.stringify(data));
};

You can see that the clients of WSS store all the WS client connections connected to WSS.

When a WS client is connected to the WS server, we need to send the information of all existing users in the room to the new users, and tell all users in the room that there are new users to join. By default, the new user entering the room is called “tourist”. The code is modified as follows:

wss.on('connection', function(ws) {
    ws.on('message', function(data) {
    });
    ws.on('close', function() {
    });
    //Give each user a separate ID
    ws.uid = uuid.v4();
    //The nickname of the new user entering the room
    ws.nick  ="Tourists";
    //Send the information of all the people in the room to new users
    for (var i in this.clients) {
        ws.send(JSON.stringify({
            nick: this.clients[i].nick,
            uid: this.clients[i].uid,
            type: "join"
        }));
    }
    //Inform all users in the room about the new users
    wss.broadcast({
        nick: ws.nick,
        uid: ws.uid,
        type: "join"
    });
});

In this way, the server-side processing of new users is completed

When a user sends a message to the server, it needs to broadcast the message and indicate the sender’s information, so modify the code:

ws.on('message', function(data) {
    wss.broadcast({
        nick: ws.nick,
        uid: ws.uid,
        time: moment(data.time).format("HH:mm:ss"),
        message: data.message,
        type: "message"
    });
});

When a WS client sends a closing request to the WS server, it needs to notify all users in other rooms, so the code is modified as follows:

ws.on('close', function() {
    wss.broadcast({
        nick: ws.nick,
        uid: ws.uid,
        type: "exit"
    });
});

When a user wants to modify his nickname, the WS client needs to send an application to the WS server, so the modification code:

ws.on('message', function(data) {
    //Parsing data
    data = JSON.parse(data);
    //If it is message, the WS client sends information to the WS server for broadcasting
    if (data.type === "message") {
        wss.broadcast({
            nick: ws.nick,
            uid: ws.uid,
            time: moment(data.time).format("HH:mm:ss"),
            message: data.message,
            type: "message"
        });
    //If it is a nickname, the WS client sends a nickname modification request to the WS server, and the user's nickname is modified and broadcast
    } else if (data.type === "nickname") {
        wss.broadcast({
            oldnick: ws.nick,
            nick: data.nick,
            uid: ws.uid,
            type: "nickname"
        });
        ws.nick = data.nick;
    }
});

The WS server of such a simple chat room is completed. All the codes are as follows:

var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({
        port: process.env.WSPORT || 3001
    });

wss.broadcast = function(data) {
    for (var i in this.clients) this.clients[i].send(JSON.stringify(data));
};

wss.on('connection', function(ws) {
    ws.on('message', function(data) {
        data = JSON.parse(data);
        if (data.type === "message") {
            wss.broadcast({
                nick: ws.nick,
                uid: ws.uid,
                time: moment(data.time).format("HH:mm:ss"),
                message: data.message,
                type: "message"
            });
        } else if (data.type === "nickname") {
            wss.broadcast({
                oldnick: ws.nick,
                nick: data.nick,
                uid: ws.uid,
                type: "nickname"
            });
            ws.nick = data.nick;
        }
    });
    ws.on('close', function() {
        wss.broadcast({
            nick: ws.nick,
            uid: ws.uid,
            type: "exit"
        });
    });
    ws.uid = uuid.v4();
    ws.nick  ="Tourists";
    for (var i in this.clients) {
        ws.send(JSON.stringify({
            nick: this.clients[i].nick,
            uid: this.clients[i].uid,
            type: "join"
        }));
    }
    wss.broadcast({
        nick: ws.nick,
        uid: ws.uid,
        type: "join"
    });
});

Implementation of websocket client


In the browser, you need to set up a WS client

//Create a WS client
var ws = new WebSocket("ws://localhost:3001");

Bind the event to it according to the API of websocket:

//After the WS client connects to the WS server, it sets the default nickname and joins the forum chat
ws.onopen = function(event) {
    $("nickname"). Val ("visitors");
    $ logs.append ("< div class: 'alert alert success'; you have joined the forum < / div >");
};
//If the WS server is shut down, a disconnect prompt is given
ws.onclose = function(event) {
    $ logs.append ("< div class: 'alert alert danger' > you have disconnected the forum chat < / div >");
};
//If the WS server sends information to this WS client:
ws.onmessage = function(event) {
    var data = JSON.parse(event.data);
    //Send a text message and display it on the page
    if (data.type === "message") {
        $chat.append("<p>" + data.nick + "(" + data.time + "): " + data.message + "</p>");
    //When a new user joins, the user joining notice is displayed and the current user list is modified
    } else if (data.type === "join") {
        if ($("p[uid='" + data.uid + "']", $users).length === 0) {
            $users.append("<p uid='" + data.uid + "'>" + data.nick + "</p>");
            $ logs.append ("<div class='alert alert-warning'>" +  data.nick  +"Joined the forum < / div >");
        }
    //If there is a user leaving, the user leaving notice will be displayed, and the current user list will be modified
    } else if (data.type === "exit") {
        $("p[uid='" + data.uid + "']", $users).remove();
        $ logs.append ("<div class='alert alert-warning'>" +  data.nick  +"Left the forum < / div >");
    //Some users modify the nickname, display the user modified nickname, modify the user list
    } else if (data.type === "nickname") {
        $("#nickname").val(data.nick);
        $("p[uid='" + data.uid + "']", $users).text(data.nick);
        $ logs.append ("<div class='alert alert-warning'>" +  data.oldnick  +"Change nickname to"+ data.nick  + "</div>");
    }
};

When you need to send information, use ws.send send out:

//Sending information data from WS client to WS server
ws.send(JSON.stringify({
    time: new Date().getTime(),
    message: message,
    type: "message"
}));

When you need to send a change nickname request, use the same method:

//Send nickname modification request from WS client to WS server
ws.send(JSON.stringify({
    nick: nick,
    type: "nickname"
}));

Such a complete WS client code:

//Create a WS client
var ws = new WebSocket("ws://localhost:3001");
//After the WS client connects to the WS server, it sets the default nickname and joins the forum chat
ws.onopen = function(event) {
    $("nickname"). Val ("visitors");
    $ logs.append ("< div class: 'alert alert success'; you have joined the forum < / div >");
};
//If the WS server is shut down, a disconnect prompt is given
ws.onclose = function(event) {
    $ logs.append ("< div class: 'alert alert danger' > you have disconnected the forum chat < / div >");
};
//If the WS server sends information to this WS client:
ws.onmessage = function(event) {
    var data = JSON.parse(event.data);
    //Send a text message and display it on the page
    if (data.type === "message") {
        $chat.append("<p>" + data.nick + "(" + data.time + "): " + data.message + "</p>");
    //When a new user joins, the user joining notice is displayed and the current user list is modified
    } else if (data.type === "join") {
        if ($("p[uid='" + data.uid + "']", $users).length === 0) {
            $users.append("<p uid='" + data.uid + "'>" + data.nick + "</p>");
            $ logs.append ("<div class='alert alert-warning'>" +  data.nick  +"Joined the forum < / div >");
        }
    //If there is a user leaving, the user leaving notice will be displayed, and the current user list will be modified
    } else if (data.type === "exit") {
        $("p[uid='" + data.uid + "']", $users).remove();
        $ logs.append ("<div class='alert alert-warning'>" +  data.nick  +"Left the forum < / div >");
    //Some users modify the nickname, display the user modified nickname, modify the user list
    } else if (data.type === "nickname") {
        $("#nickname").val(data.nick);
        $("p[uid='" + data.uid + "']", $users).text(data.nick);
        $ logs.append ("<div class='alert alert-warning'>" +  data.oldnick  +"Change nickname to"+ data.nick  + "</div>");
    }
};
//Send Message button event
$("#send").click(function(event) {
    var message = $("#message").val();
    if (message.trim() !== "") {
        //Sending information data from WS client to WS server
        ws.send(JSON.stringify({
            time: new Date().getTime(),
            message: message,
            type: "message"
        }));
    }
});
//Modify nickname button event
$("#changeNick").click(function(event) {
    var nick = $("#nickname").val();
    if (nick.trim() !== "") {
        //Send nickname modification request from WS client to WS server
        ws.send(JSON.stringify({
            nick: nick,
            type: "nickname"
        }));
    }
});

Write it at the end


Such a complete simple chat room based on websocket is completed. Try it out. Although the function is not perfect, it can be used, and it is compatible with firefox25 and chrome

Recommended Today

Statistics In PostgreSQL

This article is similar to the source reading of an article, a preliminary introduction to the PostgreSQL statistical information module. The reason why we choose PostgreSQL instead of other databases is that PostgreSQL always performs well in various papers when we see some comparison of design estimation. Statistics collected in PG In PostgreSQL, the collected […]