WebSocket下的聊天室

       websocket是解决客户端与服务器端实时通信而产生的技术。

       websocket协议允许在客户端和服务端之间建立一条双向传递信息的通道,它是建立在TCP协议之上的,首先通过”握手“来确认和建立通道,之后客户端和服务端可以通过这个通道传递信息,而不需要再次发起请求,而且客户端和服务端都可以主动的发送消息。这种技术不依赖于HTTP连接(比如XMLHttpRequest,iframe),可以实现实时消息传递。

与Socket区别:

       Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。

       WebSocket则是一个典型的应用层协议。

       Socket是传输控制层协议,WebSocket是应用层协议。

WebSocket 客户端 API :

//创建websocket对象

var ws = new WebSocket(“ws://echo.websocket.org”);

//建立连接

ws.onopen = function(){ws.send(“Test!”); };

//收到服务器消息,提取

ws.onmessage = function(evt){console.log(evt.data);ws.close();};

//关闭连接

ws.onclose = function(evt){console.log(“WebSocketClosed!”);};

//产生异常

ws.onerror = function(evt){console.log(“WebSocketError!”);};

  WebSocket 服务端 API :

我们将使用到websocket-api,这个JAR包则在Tomcat的lib下面。

//WebSocket 服务端运行在 ws://[Server 端 IP 或域名]:[Server 端口]/websockets 的访问端点,客户端浏览器已经可以对 WebSocket 客户端 API 发起 HTTP 长连接了。
@ServerEndpoint("/websocket")
 public class EchoEndpoint {

//一个新的连接建立时被调用
//Session 表明两个 WebSocket 端点对话连接的另一端,可以理解为类似 HTTPSession 的概念
 @OnOpen
 public void onOpen(Session session) throws IOException {
 //以下代码省略...
 }
 
//收到消息触发事件
//用于接收传入的 WebSocket 信息,这个信息可以是文本格式,也可以是二进制格式。
 @OnMessage
 public String onMessage(String message) {
 //以下代码省略...
 }

//MaxMessageSize 属性可以被用来定义消息字节最大限制,如果超过 6 个字节的信息被接收,就报告错误和连接关闭。
 @Message(maxMessageSize=6)
 public void receiveMessage(String s) {
 //以下代码省略...
 } 

//传输消息错误触发事件
 @OnError
 public void onError(Throwable t) {
 //以下代码省略...
 }
 
//OnClose 在连接被终止时调用。参数 closeReason 可封装更多细节,如为什么一个 WebSocket 连接关闭。
 @OnClose
 public void onClose(Session session, CloseReason reason) {
 //以下代码省略...
 } 
 
 }

聊天室:

服务器端:

package com.research.WebSocketChatRoom;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

import com.google.gson.Gson;
//用于创建和配置服务端点
@ServerEndpoint("/websocket")
public class Socket {
    public static Map<String, Session> sessionMap = new HashMap<String, Session>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    // 一个新的连接建立时被调用
    @OnOpen
    public void startSocket(Session session) {
        this.session = session;
        System.out.println("链接成功");
        if (sessionMap.size() == 0) {
            return;
        }
        Set userIds = sessionMap.keySet();
        StringBuffer sBuffer = new StringBuffer();
        for (Object str : userIds) {
            sBuffer.append(str.toString() + ":");
        }
        Gson gson = new Gson();
        try {
            Message message = new Message();
            message.setFrom("系统");
            message.setMsg(sBuffer.toString());
            session.getBasicRemote().sendText(gson.toJson(message), true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 收到消息触发事件
    @OnMessage
    public void getMessgae(Session session, String str, boolean last) {
        if (session.isOpen()) {
            try {
                System.out.println(str);
                Gson gson = new Gson();
                Message msg = gson.fromJson(str, Message.class);
                Message toMessage = msg;
                toMessage.setFrom(msg.getId());
                toMessage.setTo(msg.getTo());

                if (msg.getMsg().equals("newUser")) {
                    if (sessionMap.containsKey(msg.getId())) {
                        sessionMap.remove(msg.getId());
                    }
                    sessionMap.put(msg.getId(), session);
                } else {
                    Session toSession = sessionMap.get(msg.getTo());
                    if (toSession != null && toSession.isOpen()) {
                        toSession.getBasicRemote().sendText(gson.toJson(toMessage).toString(), last);
                    } else {
                        toMessage.setMsg("用户不存在");
                        toMessage.setFrom("系统");
                        session.getBasicRemote().sendText(gson.toJson(toMessage).toString(), last);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            System.out.println("session is closed");
        }
    }

    // 关闭连接触发事件
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        System.out.println(session.getId() + "关闭连接");
    }

    // 传输消息错误触发事件
    @OnError
    public void onError(Throwable error) {
        System.out.println(error);
    }
}

客户端:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Test WebSocket</title>
    <script type="text/javascript" src="/resource/js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript">
        $(function () {
            //服务器地址
            var url = "ws://localhost:8080/websocket";
            var ws = "";
            var message = {"id": "", "msg": "", "form": "", "to": ""};

            function connection() {
                //创建WebSocket对象
                ws = new WebSocket(url);
                console.log("connection.......");
                //收到服务器消息,e.data提取
                ws.onmessage = function (e) {
                    var json = eval('(' + e.data.toString() + ')');
                    showMessage(json.from + ":" + json.msg);
                }
                //已经关闭连接
                ws.onclose = function () {
                    showMessage("close");
                }
                //产生异常
                ws.onerror = function (e) {
                    showMessage("error");
                }
                //已经建立连接
                ws.onopen = function () {
                    showMessage("链接成功")
                    message.id = $(".identity").val();
                    message.msg = "newUser";
                    console.log(JSON.stringify(message));
                    //向服务器发送消息
                    ws.send(JSON.stringify(message));
                    message.msg = "";
                }
                //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
                window.onbeforeunload = function(){
                    ws.close();
                }

            }


            $(".start-conn-btn").click(function () {
                connection();
            });
            $(".send-btn").click(function () {//send message
                message.to = $(".to-user").val();
                message.msg = $(".msg-context").val();
                $(".msg-context").val("");
                ws.send(JSON.stringify(message));
                showMessage("我:" + message.msg);
                message.msg = "";

            });

            function showMessage(msg) {
                $(".show-message").append(msg + "<br/>");

            }


        });

    </script>
</head>
<body>
<div class="container">
    <div calss="item">
        <span>ID:</span>
        <input type="text" class="identity">
        <button class="start-conn-btn">链接</button>
        <span>toUser:</span>
        <input type="text" class="to-user">
    </div>
    <div class="show-message">

    </div>
    <div calss="item">
        <span>内容:</span>
        <textarea class="msg-context"></textarea>
    </div>
    <div>
        <button class="send-btn">send</button>
    </div>
</div>
</body>

</html>

启动:

/*
 * 文 件 名:  ChanatRoom.java
 * 版    权:  
 * 描    述:  <描述>
 * 修 改 人:   sun
 * 修改时间:  2018年7月18日
 */
package com.home.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * <一句话功能简述>
 * <功能详细描述>
 * 
 * @author   sun
 * @version  [版本号, 2018年7月18日]
 */
@Controller
@RequestMapping("/chanat-room")
public class ChanatRoom
{
    @RequestMapping("/start")
    public String start()
    {
        return "/chatRoom/chat";
    }
    
}

猜你喜欢

转载自blog.csdn.net/Java_Mrsun/article/details/81772147