A few days ago, I made a simple chat room, realizing the chat function, the chat content can send text, pictures, audio, video, emoticons and other content, support one-to-one chat, group chat. Now before the chat room function to do a simple comb and summary.

directory

  • The principle is briefly
  • The function development
  • Effect of experience

The principle is briefly

This time, socket. IO was used for communication.

webscoket

Html5 has websocket functionality, see this article “WEBSocket summary of HTML knowledge” for more basic knowledge.

WebSocket is a protocol that implements full-duplex communication over a single TCP connection, saving server resources and bandwidth and enabling real-time communication.

Extracurricular science popularization:

Communication is classified into parallel communication, serial communication, synchronous/asynchronous, simplex/duplex, half duplex/full duplex.

  • Parallel communication means that bits of data are sent or received simultaneously on multiple data lines. Simple control, fast transmission speed; Because there are many transmission lines, it is suitable for short distance communication.
  • Serial communicationData bits are sent and received bit by bit on the same data line. Complex control, slow transmission speed; Only need one data line, suitable for long distance communication.
    • It can be divided into synchronous serial communication mode and asynchronous communication mode according to the demarcation, timing and synchronization method of data flow.
    • According to the direction of transmission of serial data, we can classify communication into simplex, half duplex and duplex.
      • Simplex: Indicates that data can be transmitted only in one direction.
      • Half duplex: Indicates that data can be transmitted in two directions, but needs to be transmitted in time.
      • Full-duplex: Indicates that data can be transmitted both ways at the same time.

socket.io

Socket. IO is a mature solution based on webSocket protocol. Advantages are good performance, support multiple platforms; The disadvantage is that the data transmitted does not fully comply with the WebSocket protocol, which requires both the client and server to use the socket. IO solution.

The difference between

  • HTTP and Webscoket are both based on TCP;
  • HTTP establishes short connections;
  • Websocket establishes a long connection;

The function development

Now this function is analyzed and the development of front-end and back-end content, first to get through the back-end part, for the front-end connection socket service preparation.

The following shows the most basic chat room, including the following functions:

  • Many people chat
  • Displays the user name and number of users
  • Press enter to send
  • To the top

In the back-end

Here is how to set up a Socket server in node.

Installing dependency packages

npm install -g express-generator
express --view=ejs chat
cd chat
npm install
npm install socket.io
Copy the code

Configure the socket. IO

Open the bin/ WWW file, var server = http.createserver (app); The next line writes the following.

The following content is a separate introduction to each content, not all code paste.

  • Introducing WS services
const ws = require('socket.io');
const io = ws(server, {
  path: '/chat'.transports: [
    'polling'.'websocket']})Copy the code

Commonly used method

  • Connect and disconnect
io.on('connection'.socket= > {

    console.log('a user connected! ');

    //disconnect
    socket.on('disconnect'.() = > {
        console.log('a user disconnected! '); })}Copy the code
  • Join and leave the room
// join room
socket.join(roomId);

// leave room
socket.leave(roomId);
Copy the code
  • Receive a message
socket.on('event name'.data= > {
    // data
}
Copy the code
  • Send a message
socket.emit('event name', {
    // some data
});
Copy the code
  • Broadcast to others
socket.broadcast.emit('event name', {
    // some data
});
Copy the code
  • Send a message to a room
io.to(roomId).emit('event name', {
    // some data
})
Copy the code

The summary procedure

let roomInfo = {};

io.on('connection'.socket= > {
  let roomId = socket.handshake.query.roomId;

  // user login
  socket.on('login'.data= > {
    
    socket.join(roomId);

    if(! (roomIdin roomInfo)) {
      roomInfo[roomId] = [];
    }

    let names = [];
    let users = roomInfo[roomId];
    if (users.length) {
      for (let i = 0; i < users.length; i++) {
        names.push(users[i].name);
      }
      if(! (names.includes(data.user))) { users.push({id: socket.id,
          name: data.name,
          avatar: data.avatar
        })
      }
    } else {
      roomInfo[roomId].push({
        id: socket.id,
        name: data.name,
        avatar: data.avatar
      });
    }

    console.log('roomInfo: ', roomInfo);

    io.to(roomId).emit('system', {
      name: data.name,
      users: roomInfo[roomId]
    })

  })

  // client msg
  socket.on('message'.data= > {
    io.to(roomId).emit('chat', data);
  })

  // leave room
  socket.on('leave'.data= > {
    let users = roomInfo[roomId];
    if (users && users.length) {
      for (let i = 0; i < users.length; i++) {
        const user = users[i];
        if (data.name == user.name) {
          users.splice(i, 1);
        }
        
      }
    }

    socket.leave(roomId);

    io.to(roomId).emit('logout', {
      name: data.name,
      users: roomInfo[roomId]
    })

    console.log('roomInfo: ', roomInfo);

  })

  socket.on('disconnect'.() = > {
    console.log('a user disconnect! '); })});Copy the code

The front side

  • The introduction ofsocket.io.jsfile
<script src="./js/socket.io.js"></script>
Copy the code
  • HTML part

Login interface:

<div class="chat">
  <h2>XQ chat room</h2>
  <form class="chat-form">
      <p>
          <label for="name">Nickname:</label>
          <input type="text" id="name" name="name" placeholder="Please enter user name" required>
      </p>
      <p>
          <label for="avatar">Head:</label>
          <select name="avatar" id="avatar" required>
              <option value="avatar1">Picture 1</option>
              <option value="avatar2">Picture 2</option>
              <option value="avatar3">Picture 3</option>
          </select>
      </p>
      <p>
          <label for="roomId">Room:</label>
          <select name="roomId" id="roomId" required>
              <option value="1">Room 1</option>
              <option value="2">Room 2</option>
              <option value="3">Room 3</option>
          </select>
      </p>
      <p>
          <input type="submit" value="Enter the room">
      </p>
  </form>
</div>
Copy the code

Room interface:

<div class="room">
    <div class="room-header">
        <h3>XQ Chat room (<span class="count">0</span>)</h3>
        <button class="logout">exit</button>
    </div>
    <div class="room-nav">
        <small>Number of online users:</small>
        <span id="room-users">No member of the</span>
    </div>
    <ul class="room-content">
    </ul>
    <div class="room-footer">
        <input class="room-ipt" type="text" placeholder="Just write it down.">
        <input class="room-btn" type="submit" value="Send">
    </div>
</div>
Copy the code
  • The CSS part
body {
    margin: 0;
    padding: 0;
    background: #f9f9f9;
}

h1.h2.h3.h4.h5.h6.p {
    margin: 0;
}

ul.li {
    margin: 0;
    padding: 0;
    list-style: none;
}

.chat {
    box-sizing: border-box;
    margin: 50px auto;
    padding: 20px;
    width: 300px;
    height: auto;
    background: #fff;
}

.chat.active {
    display: none;
}

.chat h2 {
    margin-bottom: 10px;
    font-size: 18px;
    line-height: 1.5;
    text-align: center;
}

.chat-form p {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px 0;
    font-size: 15px;
    line-height: 35px;
}

.chat-form p label {
    width: 50px;
}

.chat-form p input..chat-form p select {
    flex: 1;
    box-sizing: border-box;
    padding: 0 10px;
    height: 30px;
    border: 1px solid #ccc;
    outline: none;
    background: none;
}

.chat-form p input:focus..chat-form p select:focus {
    box-shadow: 0 0 5px #ccc;
}

.room {
    display: none;
    width: 100%;
    height: 100vh;
    overflow: hidden;
}

.room.active {
    display: flex;
    flex-direction: column;
}

.room-header {
    position: relative;
    display: flex;
    justify-content: space-between;
    align-items: center;
    box-sizing: border-box;
    padding: 0 15px;
    height: 60px;
    background: # 111;
    color: #fff;
}

.room-header h3 {
    font-size: 18px;
    text-align: left;
}

.room-header button {
    width: 50px;
    height: 50px;
    background: none;
    color: #fff;
    outline: none;
    border: none;
    text-align: right;
}

.room-nav {
    box-sizing: border-box;
    padding: 20px 15px;
    line-height: 30px;
    font-size: 14px;
}

.room-nav small,
.room-nav span {
    font-size: 14px;
}

.room-nav span {
    color: rgb(6.90.146);
}

.room-content {
    flex: 1;
    padding: 15px 0;
    background: #fff;
    border-top: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
    background: #eee;
    overflow-x: hidden;
    overflow-y: auto;
}

.room-content li {
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
    box-sizing: border-box;
    padding: 15px 10px;
    margin-bottom: 10px;
    width: 100%;
}

.room-content li .room-user {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.room-content li img {
    display: inline-block;
    width: 40px;
    height: 40px;
}

.room-content li span {
    font-size: 14px;
}

.room-des {
    position: relative;
    margin-top: 5px;
    margin-left: 10px;
    box-sizing: border-box;
    padding: 3px 5px;
    font-size: 14px;
    line-height: 30px;
    background: #ccc;
    border-radius: 5px;
}

.room-des::before..room-des::after {
    content: ' ';
    position: absolute;
    top: 10px;
    width: 0;
    height: 0;
    border: 5px solid transparent;
}

.room-des::before {
    display: inline-block;
    left: -10px;
    border-right: 5px solid #ccc;
}

.room-des::after {
    display: none;
    right: -10px;
    border-left: 5px solid #fff;
}

.room-me {
    flex-direction: row-reverse;
}

.room-me .room-des {
    margin-left: 0;
    margin-right: 10px;
    background: #fff;
}

.room-me .room-des::before {
    display: none;
}

.room-me .room-des::after {
    display: inline-block;
}

.room-content .system {
    justify-content: center;
    align-items: center;
    padding: 0;
    height: 35px;
    line-height: 35px;
}

.system p {
    box-sizing: border-box;
    padding: 0 5px;
    font-size: 14px;
    text-align: center;
    border-radius: 5px;
    background: #ccc;
}

.room-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 50px;
    background: #fff;
    border-top: 1px solid #ccc;
}

.room-footer .room-ipt {
    margin-top: 1px;
    box-sizing: border-box;
    padding: 10px;
    width: 80%;
    height: 48px;
    background: none;
    border: 1px solid transparent;
    outline: none;
}

.room-footer .room-ipt:focus {
    border: 1px solid #ccc;
    box-shadow: 0 0 5px #ccc;
}

.room-footer .room-btn {
    width: 19%;
    height: 100%;
    background: rgb(2.54.112);
    border: 1px solid #ccc;
    outline: none;
    font-size: 15px;
    color: #fff;
}
Copy the code
  • Js part

Login interface js

let chat = document.querySelector('.chat');
let chatForm = document.querySelector('.chat-form');
let user = document.querySelector('#name');
let avatar = document.querySelector('#avatar');
let roomId = document.querySelector('#roomId');

// io
let socket = io.connect('/', {
    path: '/chat'
});

// login
chatForm.onsubmit = function(){
    let userInfo = {
        name: user.value,
        avatar: `/img/${avatar.value}.webp`.roomId: roomId.value
    }
    localStorage.setItem('userInfo'.JSON.stringify(userInfo));
    checkLogin();
    return false;
};

checkLogin();

function checkLogin () {

    let userInfo = localStorage.getItem('userInfo');
    userInfo = JSON.parse(userInfo);

    if (userInfo && userInfo.name) {
        chat.classList.add('active');
        room.classList.add('active');
        socket.emit('login', userInfo);

    } else {
        chat.classList.remove('active');
        room.classList.remove('active'); }}Copy the code

Js for the room section

let room = document.querySelector('.room');
let logout = document.querySelector('.logout');
let count = document.querySelector('.count');
let roomUsers = document.querySelector('#room-users');
let roomContent = document.querySelector('.room-content');
let roomIpt = document.querySelector('.room-ipt');
let roomBtn = document.querySelector('.room-btn');

// Log out
logout.addEventListener('click'.function(){
    let userInfo = localStorage.getItem('userInfo');
    userInfo = JSON.parse(userInfo);
    socket.emit('leave', userInfo);
    alert('Exit successful! ');
    localStorage.removeItem('userInfo');
    checkLogin();
})

roomIpt.addEventListener('keyup', sendMsg, false);
roomBtn.addEventListener('click', sendMsg, false);

// Send a message
function sendMsg (e) {
    if (e.type === 'click' || e.code === 'Enter') {
        let val = roomIpt.value;
        if (val == ' ') {
            alert('Chat content cannot be empty! ');
            return false;
        }
        let userInfo = localStorage.getItem('userInfo');
        userInfo = JSON.parse(userInfo);
        userInfo.msg = val;
        roomIpt.value = ' ';
        socket.emit('message', userInfo);
        goBot();
    }
}

goBot();

/ / to the bottom
function goBot () {
    roomContent.scrollTop = roomContent.scrollHeight;
}

// System message prompt
function welcome (user = 'mark', type = 1) {
    roomContent.innerHTML += '<li class="system"> <p>${user}</strong>${type == 1 ? '来到' : 'leave'}This room! </p> </li> `;
    goBot();
}

// System message
socket.on('system'.data= > {
    let strs = ' ';
    welcome(data.name);
    count.innerText = data.users.length;
    for (const item of data.users) {
        strs += item.name + ', ';
    }
    roomUsers.innerText = ' ';
    roomUsers.innerText += strs;
})


// Exit alert
socket.on('logout'.data= > {
    let strs = ' ';
    welcome(data.name, 2);
    count.innerText = data.users.length;
    for (const item of data.users) {
        strs += item.name + ', ';
    }
    roomUsers.innerText = ' ';
    roomUsers.innerText += strs;
})

// Accept the message
socket.on('chat'.data= > {
    let userInfo = localStorage.getItem('userInfo');
    userInfo = JSON.parse(userInfo);
    let isUser = data.name == userInfo.name;
    roomContent.innerHTML += `
        <li ${isUser ? 'class="room-me"' : ' '}>
            <div class="room-user">
                <img class="room-avatar" src="/chatroom/${(isUser ? userInfo.avatar : data.avatar ) || '/img/avatar1.webp'}" alt="">
                <span class="room-name">${isUser ? userInfo.name : data.name }</span>
            </div>
            <p class="room-des">${data.msg}</p>
        </li>
    `;
    goBot();
})
Copy the code

Effect of experience

Finally done, next to experience the beautiful life of online surfing -XQ chat room!

  • Enter the room

First, enter your own nickname, select your avatar and room, and click the enter room button to talk.

  • Send a message

Then, enter the message content, click the Send button, or pressEnterEnter will also work.

You can open a privacy screen or a new browser, open the url, and enter another test account

This is what Jerry looks like when he logs in

This is jerry’s message that Mark saw

  • Log out

If the chat is over, you can click on the upper right to exit the chat room.

This is what Mark saw after Jerry logged out

Take a look at the user information printed out at the back end.

  • This is the information mark logged in

  • This is what Jerry logged on to

  • This is what Jerry recorded after he quit

The above is a summary of a simple chat room and websocket knowledge in Node.