相关文章推荐
难过的炒饭  ·  正则 test() ...·  2 年前    · 
焦虑的皮带  ·  c#system.outofmemoryex ...·  2 年前    · 

最近在学习webSocket这一块内容。先是做了个简单的聊天室,然后就遇到问题了。

@ServerEndpoint("/hall/{nickName}")
@Component
public class Hall {
    //当前在线人数
    private static int onlineCount = 0;
    //每个客户端对应的session
    private static ConcurrentHashMap<String,Session> webSocketMap = new ConcurrentHashMap<>();
    @OnOpen
    public void onOpen(Session session, @PathParam("nickName")String nickName) throws IOException {
        if (webSocketMap.containsKey(nickName)){
            sendMessage(webSocketMap.get(nickName),"已在其他地方登录");
            onClose(nickName);
            webSocketMap.put(nickName,session);
        }else {
            webSocketMap.put(nickName,session);
            onlineCount++;
            sendToAll(nickName+"进入大厅");
     * 连接关闭调用的方法
    @OnClose
    public void onClose(@PathParam("nickName")String nickName){
        if (webSocketMap.containsKey(nickName)) {
            webSocketMap.remove(nickName);
            onlineCount--;
            sendToAll(nickName+"离开了大厅");
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
    @OnMessage
    public void onMessage(@PathParam("nickName")String nickName,String message) {
        //群发消息
        for(Session session: webSocketMap.values()){
            try {
                message = nickName+":"+message;
                sendMessage(session,message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
    public void sendMessage(Session session,String message) throws IOException {
        session.getBasicRemote().sendText(message);
    public void sendToAll(String message){
        //群发消息
        for(Session session: webSocketMap.values()){
            try {
                sendMessage(session,message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
var websocket = null;
var nickName = document.getElementById('nickName').innerHTML;
window.onload = () => {
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/hall/" + nickName);
    } else {
        alert('当前浏览器不支持websocket')
    //连接成功建立的回调方法
    websocket.onopen = function () {
        // showMessage("<span style='color: green'>连接成功!</span><br/>");
    //发生了错误事件
    websocket.onerror = function() {
        showMessage("<span style='color:red'>与服务器连接发生错误</span>");
    //获得消息
    websocket.onmessage = function (message) {
        showMessage(message.data);
    //关闭事件
    websocket.onclose = function () {
        showMessage("与服务器连接已断开");
//显示信息
function showMessage(message) {
    let messageBox = document.getElementById('messageBox');
    messageBox.innerHTML += message+"<br/>" ;
send.onclick = () => {
    let message = document.getElementById('message');
    websocket.send(message.value);
    message.value = "";
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
    websocket.close();

以上是服务端和客户端的代码。

当我在测试同一用户名在异地登录的时候,确实服务端不会再给原来的浏览器发送任何消息了。但是原来的浏览器还能给服务端发送消息啊。

所以我在想,服务端如何发起断开连接请求,告诉客户端,去断开连接

服务端主动断开客户端链接的时候,可以给两个参数,一个是code,一个是reason。表示状态码和断开的原因。

void close(CloseReason closeReason) throws IOException; public CloseReason(CloseReason.CloseCode closeCode, String reasonPhrase);

客户端可以监听到这个 onclose事件,并且从event对象中获取到这两个属性。

websocket.onclose(event) => {
    const code = event.code;
    const reason = event.reason;
                             评论 (3)