WebSocket实现简易版的多人聊天室

一、websocket简介     

     WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。(百度百科)

二、多人聊天室的实现

1、后端服务器

(1)后端使用springboot搭建服务器,在IDEA中新建一个springboot工程,在pom.xml文件中引入spring-boot-starter-websocket依赖

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

(2)写一个配置类

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

(3)controller

package com.joe.study.eshopdemo.controller;

import org.springframework.stereotype.Controller;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Controller
@ServerEndpoint("/groupChat/{roomId}/{username}")
public class GroupChatController {

    // 保存 聊天室id -> 聊天室成员 的映射关系
    private static ConcurrentHashMap<String, List<Session>> rooms = new ConcurrentHashMap<>();

    // 收到消息调用的方法,群成员发送消息
    @OnMessage
    public void onMessage(@PathParam("roomId") String roomId,
                          @PathParam("username") String username, String message) {
        List<Session> sessionList = rooms.get(roomId);
        // 分别向聊天室的成员发送消息
        sessionList.forEach(item -> {
            try {
                String text = username + ": " + message;
                item.getBasicRemote().sendText(text);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    // 建立连接调用的方法,群成员加入
    @OnOpen
    public void onOpen(Session session, @PathParam("roomId") String roomId) {
        List<Session> sessionList = rooms.get(roomId);
        if (sessionList == null) {
            sessionList = new ArrayList<>();
            rooms.put(roomId, sessionList);
        }
        sessionList.add(session);
        System.out.println("成员加入---- 聊天室号:" + roomId + "  当前聊天室人数:" + sessionList.size());
    }

    // 关闭连接调用的方法,群成员退出
    @OnClose
    public void onClose(Session session, @PathParam("roomId") String roomId) {
        List<Session> sessionList = rooms.get(roomId);
        sessionList.remove(session);
        System.out.println("成员退出---- 聊天室号:" + roomId + "  当前聊天室人数:" + sessionList.size());
    }

    // 传输消息错误调用的方法
    @OnError
    public void OnError(Throwable error) {
        System.out.println("消息传递出错");
    }
}

2、前端

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>websocket多人聊天室</title>

    <style>
	  .container {
		margin-top: 30px;
		margin-left: 30px;
	  }
      .span1 {
        display: inline-block;
        width: 80px;
        font-size: 13px;
      }
      input {
        width: 200px;
        height: 30px;
        outline: none;
        border: 1px solid #3998f7;
        border-radius: 3px;
        padding: 0 10px;
      }
      input:hover,
      textarea:hover {
        box-shadow: 0 0 3px #3998f7;
      }
      #name {
        margin-top: 15px;
      }
      button {
        width: 100px;
        height: 30px;
        outline: none;
        color: #fff;
        font-size: 13px;
        font-weight: bold;
        background-color: #168ed1;
        border: none;
        border-radius: 5px;
        cursor: pointer;
      }
      #connectBtn,
      #content,
      #sendBtn,
      #closeBtn {
        margin-top: 10px;
      }
	  #messages {
		margin-top: 20px;
	  }
      textarea {
        width: 300px;
        height: 80px;
        outline: none;
        border: 1px solid #3998f7;
        border-radius: 3px;
        color: rgba(0, 0, 0, 0.7);
        font-size: 13px;
        font-weight: bold;
        padding: 5px;
      }
      #messages, .me, .name {
        color: rgba(0, 0, 0, 0.7);
        font-size: 14px;
        font-weight: bold;
      }
	  .me {
		color: red;
	  }
	  .name {
		color: royalblue;
	  }
    </style>
	</head>
	
  <body>
    <div class="container">
      <span class="span1">聊天室id:</span><input type="text" id="roomId" placeholder="请输入聊天室id" /><br />
      <span class="span1">昵称:</span><input type="text" id="name" placeholder="请输入你的昵称" /><br />
      <button id="connectBtn">连接</button><br />
      <textarea id="content" placeholder="请输入要发送的消息"></textarea><br />
      <button id="sendBtn">发送</button>
      <button id="closeBtn">退出</button><br />
	  <div id="messages"></div>
    </div>

    <script type="text/javascript">
      const connectBtn = document.getElementById("connectBtn");
      const sendBtn = document.getElementById("sendBtn");
      const closeBtn = document.getElementById("closeBtn");
      const roomIdDOM = document.getElementById("roomId");
      const nameDOM = document.getElementById("name");
      const messagesDOM = document.getElementById("messages");
      const contentDOM = document.getElementById("content");
      let webSocket = null;

      // 加入聊天室
      connectBtn.addEventListener("click", () => {
        const roomId = roomIdDOM.value;
        const name = nameDOM.value;
        if (!roomId || !name) {
          alert("房间号和用户名不能为空");
          return;
        }
        const url = "ws://localhost:8787/groupChat/" + roomId + "/" + name;
        webSocket = new WebSocket(url);

        webSocket.onerror = e => {
          alert("出错了");
        };
        webSocket.onopen = e => {
		  messagesDOM.innerHTML = "您已加入聊天室!";
		  connectBtn.style.display = 'none'
        };

        webSocket.onmessage = e => {
		  const nickname = e.data.split(":")[0];
		  const data = e.data.slice(e.data.indexOf(':') + 1)
          messagesDOM.innerHTML += `<br /><span class='${
            nickname === name ? "me" : "name"
          }'>${nickname === name ? "我" : nickname}: </span>&nbsp&nbsp;${data}`;
        };

        webSocket.onclose = e => {
		  connectBtn.style.display = 'none'
		  alert("您已退出聊天室");
        };
      });

      // 发送消息
      sendBtn.addEventListener("click", () => {
        webSocket.send(contentDOM.value);
        contentDOM.value = "";
      });

      // 退出聊天室
      closeBtn.addEventListener("click", () => {
        webSocket.close();
      });
    </script>
  </body>
</html>

 3、效果

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值