WebSocket

1.简介

websocket是基于tcp的一种新的网络协议,它实现了浏览器与服务器的全双工通信,浏览器只需要与服务器进行一次握手,两者就可以建立持续性的连接,并双向数据传输
WebSocket_第1张图片

WebSocket_第2张图片
websocket应用场景:视频弹幕,网页聊天,体育实况更新,股票基金报价

2.websoclet简易聊天室

1.实现websocket聊天室,需要前端向后端发起握手验证,即在前端创建一个socket对象,向后端发起握手验证
2.websocket是端到端之间的通信,需要在后端申明为服务器端点

//配置类,ServerEndpointExporter该对象用于申明服务端
@Configuration
public class SocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3.前后端都有三个方法onopen\onclose\onmessage
onopen:建立连接时,进行xxx操作
onclose:关闭连接时,进行xxx操作
onmeaasge:发送消息

具体案例:

//加入聊天室之前,登录验证,index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>登录页</title>
</head>
<body>
<label for="username">Username:</label>
<input id="username" type="text" placeholder="请输入昵称">
<button id="submit" >ENTER</button>
</body>
<script>
    var submit = document.getElementById('submit');
    submit.addEventListener('click',function(){
        window.location.href = 'homepage.html?username=' + document.getElementById('username').value;
    })
</script>
</html>
//homepage,创建和使用socket
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>房间</title>
</head>

<body>
<button onclick="wsClose()">退出房间</button>
<br/><br/>
<div id="showMessage"></div>
<br/><br/>
<input id="sendMessage" type="text"/>
<button onclick="sendMessage()">发送消息</button>
</body>

<script>
    // 获取url参数的昵称
    function getQueryVariable(variable) {
        var query = window.location.search.substring(1);
        var vars = query.split("&");
        for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            if(pair[0] == variable){return pair[1];}
        }
        return(false);
    }
    var conn = "ws://localhost:8080/wechat/" + getQueryVariable("username");

    // webSocket连接
    var ws = new WebSocket(conn);

    // 连接错误要做什么呢?
    ws.onerror = function () {
        showMessageInnerHTML("发生未知错误错误");
    }
    // 客户端连接需要干什么呢?
    ws.onopen = function () {
        showMessageInnerHTML("------------连接上聊天室---------------");
    }

    // 客户端关闭需要干什么呢?
    ws.onclose = function () {
        showMessageInnerHTML("退出了当前房间");
    }

    // 收到消息
    ws.onmessage = function (even) {
        showMessageInnerHTML(even.data);
    }

    // 关闭浏览器时
    window.onbeforeunload = function () {
        ws.wsClose();

    }

    // 网页上显示消息
    function showMessageInnerHTML(msg) {
        document.getElementById('showMessage').innerHTML += msg + '
'
; } // 发送消息 function sendMessage() { var msg = document.getElementById('sendMessage').value; ws.send(msg); document.getElementById('sendMessage').value = ''; } // 关闭连接 function wsClose() { ws.close(); } </script> </html>
//SocketConfig,申明socket的服务器端
@Configuration
public class SocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
@Component // 注解虽然单例,但还是会创建多例
@ServerEndpoint(value = "/wechat/{username}")  // 声明为服务器端点
public class Myserver {

    // 成员变量
    private Session session;
    private String username;

    // 类变量
    // 类变量涉及同步问题,用线程安全类
    // 可以用<String room,<String username,MyServer> >来形成房间
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    private static ConcurrentHashMap<String, Myserver> map = new ConcurrentHashMap<>();

    // 连接
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) throws IOException {
        this.session = session;
        this.username = username;
        map.put(username, this);
        addOnlineCount();
        sendMessageAll(username + "加入了房间,当前在线人数:" + getOnlineCount());
    }

    // 关闭
    @OnClose
    public void onClose() throws IOException {
        subOnlineCount();
        map.remove(username);
        sendMessageAll(username + "退出了房间,当前在线人数:" + getOnlineCount());
    }

    // 发送错误
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    // 默认群发
    @OnMessage
    public void onMessage(String message) throws IOException {
        sendMessageAll(username + ":" + message);
    }

    // 群发
    private void sendMessageAll(String message) throws IOException {
        for (Myserver value : map.values()) {
            value.session.getBasicRemote().sendText(message);    // 阻塞式
            // this.session.getAsyncRemote().sendText(message);  // 非阻塞式
        }
    }

    // 私发
    private void sendMessageTo(String message, String to) throws IOException {
        Myserver toUser = map.get(to);
        toUser.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount.get();
    }

    public static synchronized void addOnlineCount() {
        Myserver.onlineCount.getAndIncrement();
    }

    public static synchronized void subOnlineCount() {
        Myserver.onlineCount.getAndDecrement();
    }
}

//pom
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

WebSocket_第3张图片

你可能感兴趣的:(websocket,网络协议,网络)