IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 初学WebSocket -> 正文阅读

[网络协议]初学WebSocket

介绍

WebSocket本质上一种计算机网络应用层的协议,用来弥补http协议在持久通信能力上的不足。
相对于HTTP这种非持久的协议来说,Websocket是一个持久化的协议
Websocket是一种在单个TCP连接上进行全双工通讯的协议,双工(duplex)是指两台通讯设备之间,允许有双向的资料传输。全双工的是指,允许两台设备间同时进行双向数据传输。这是相对于半双工来说的,半双工不能同时进行双向传输,这期间的区别相当于手机和对讲机的区别,手机在讲话的同时也能听到对方说话,对讲机只能一个说完另一个才能说。
在Websocket协议中,客户端和服务端只需要做一个握手的动作,就能形成一条通道,两者之间可以进行数据互相传送。


优点

  • 较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小
  • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应。
  • 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。
  • 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
  • 可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
  • 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

握手

WebSocket不同于传统的Socket三次握手不同,由于WebSocket借用了HTTP协议,只需要一次握手即可创建连接。
以下信息可以在浏览器的开发者工具中的Network中查看

  1. 客户端发送请求
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: Upgrade
Host: 8.210.193.111:21001
Origin: null
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: NK3v4ty5lHerm65s/Y0G/A==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
  • Connection和Upgrade:用于表明发起的是WebSocket协议请求
  • Sec-WebSocket-Extensions:表示客户端想要表达的协议级的扩展
  • Sec-WebSocket-Key:是一个base64编码值,有浏览器随机生成
  • Sec-WebSocket-Version:表明客户端的协议版本
  1. 服务器回应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 2Hn3Z+/YRWG0UycOhCJNA4JnxOI=
  • HTTP/1.1 101 Switching Protocols:表示建立好连接,并切换了TCP协议
  • Connection和Upgrade:用于表明发起的是WebSocket协议请求
  • Sec-WebSocket-Accept:这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。

Websocket的作用

  • 不需要用HTTP轮询实现的“长连接”,每隔几秒钟向接口服务器请求新消息。需要不断的建立HTTP连接,等待服务器响应。
  • HTTP的生命周期通过Request来界定,也就是一个Request 一个Response,那么在HTTP1.0中,这次HTTP请求就结束了。
  • 接口服务器不能主动推送新的消息到客户端
  • HTTP还是一个无状态协议,(每次请求都需要传userId,userToken)

而webSocket建立起连接后,通过第一次的用户校验后,之后就不需要再次校验,服务端就可以主动推送消息到客户端。


WS和WSS

  • ws协议:普通请求,占用与http相同的80端口;
  • wss协议:基于SSL的安全传输,占用与tls相同的443端口。

实现

  • java(需要java8版本)
  • 添加javax.websocket jar包
  • 实现 WebSocketTest.java
  • 实现 PlayerManager.java
@ServerEndpoint(value = "/websocketTest/{userId}/{userName}")
public class WebSocketTest {

    private String userId;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    private Session session;

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, @PathParam("userName") String userName, Session session) {
        System.out.println("新连接:" + userId + " , " + userName);
        this.userId = userId;
        this.session = session;
        PlayerManager.addPlayer(userId, this);
    }

    @OnClose
    public void onClose() {
        System.out.println("连接关闭:" + userId);
        PlayerManager.removePlayerSession(userId);
    }

    @OnMessage
    public void onMessage(String msg, Session session) throws IOException {
        System.out.println("收到消息: " + msg);
        if ("all".equals(msg)) {
            sendAll(msg);
        } else {
            session.getBasicRemote().sendText(msg);
            send2Player(msg, "333");
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("连接发送错误");
        error.printStackTrace();
    }

    public void send2Player(String msg, String userId) throws IOException {
        WebSocketTest wst = PlayerManager.getPlayerSession(userId);
        if (null == wst) {
            return;
        }
        wst.getSession().getBasicRemote().sendText(msg);

    }

    public void sendAll(String msg) throws IOException {
        List<WebSocketTest> list = PlayerManager.getAllSession();
        for (int i = 0; i < list.size(); i++) {
            list.get(i).getSession().getBasicRemote().sendText(msg);
        }
    }

}
public class PlayerManager {
    private static Map<String, WebSocketTest> playerSessionMap = new HashMap<>();

    public static void addPlayer(String userId, WebSocketTest playerSession) {
        if (userId == null || userId.equals("") || playerSessionMap == null) {
            return;
        }
        playerSessionMap.put(userId, playerSession);
    }

    public static List<WebSocketTest> getAllSession() {
        List<WebSocketTest> list = new ArrayList<>();
        for (WebSocketTest wst : playerSessionMap.values()) {
            list.add(wst);
        }
        return list;
    }

    public static WebSocketTest getPlayerSession(String userId) {
        if (userId == null) {
            return null;
        }
        WebSocketTest wst = null;
        if (playerSessionMap.containsKey(userId)) {
            wst = playerSessionMap.get(userId);
        }
        return wst;
    }

    public static void removePlayerSession(String userId) {
        if (userId == null) {
            return;
        }
        if (playerSessionMap.containsKey(userId)) {
            playerSessionMap.remove(userId);
        }
    }
}
  • html客户端
<!DOCTYPE html> 
<html lang="zh-CN"> 
<head> 
	<meta charset="utf-8"> 
	<title></title> 
</head> 
<body> 
    <span>
        id <input type="text" id="userId">
    </span>
    <br/>
    <span>
        昵称 <input type="text" id="userName">
    </span>
    <br/>
    <span>
        内容 <input type="text" id="msg">
    </span>
    <br/>
    <button onclick="openSession()">连接</button>
    <button onclick="send()">发送</button>
    <button onclick="closeWebsocket()">关闭</button>
    <div id="message"></div>
</body> 
<script>
    var ws;



    function openSession() {
        var userId = document.getElementById("userId").value;
        var userName = document.getElementById("userName").value;
        console.log('ws:localhost:8080/MavenTest_war_exploded/websocketTest/' + userId + '/' + userName)
        ws = new WebSocket('ws:localhost:8080/MavenTest_war_exploded/websocketTest/' + userId + '/' + userName);
        ws.onerror = onerror
        ws.onopen = onopen
        ws.onmessage = onmessage
        ws.onclose = onclose
    }

    // 连接安生错误的回调方法
    function onerror() {
        setMessageInnerHTML("WEBSOCKET发生链接错误");
    }

    // 连接成功的回调方法
    function onopen(ev) {
        setMessageInnerHTML("WebSocket连接成功!");
    }

    // 收到消息的回调方法
    function onmessage(ev) {
        setMessageInnerHTML(ev.data);
    }

    // 连接关闭的回调方法
    function onclose() {
        setMessageInnerHTML("WebSocket连接关闭");
    }

    // 监听窗口关闭事件,防止连接没断关闭窗口。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    // 将消息显示在网页上
    function setMessageInnerHTML(innerHtml){
        document.getElementById("message").innerHTML += '收到回应:' + innerHtml + '<br />'
    }

    // 关闭websocket连接
    function closeWebsocket(){
        ws.close();
    }

    // 发送消息
    function send(){
        var message = document.getElementById("msg").value;
        ws.send(message);
    }

</script>
</html>

http和https

HTTP是一个基于TCP/IP通信协议来传递数据的协议,HTTP协议一般用于B/S架构,常用的请求方法有GET、POST、HEAD

1. HTTP与HTTPS有什么区别?

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:

  • https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  • http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
2. 客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤
  • 客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
  • Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
  • 客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
  • 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
  • Web服务器利用自己的私钥解密出会话密钥。
  • Web服务器利用会话密钥加密与客户端之间的通信。
    在这里插入图片描述
3. URI和URL的区别
  • HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。
  • URI:Uniform Resource Identifier 统一资源标识符(身份证号)
  • URL:Uniform Resource Location 统一资源定位符(住址)
  • URI 是用来标识一个具体的资源的,我们可以通过 URI 知道一个资源是什么。
  • URL 则是用来定位具体的资源的,标识了一个具体的资源位置。互联网上的每个文件都有一个唯一的URL。

参考文档:

WebSocket 是什么原理?为什么可以实现持久连接? - 知乎
java WebSocket开发入门WebSocket
浅谈WebSocket协议、WS协议和WSS协议原理及关系
十分钟搞懂HTTP和HTTPS协议?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:36:22  更:2021-09-18 10:38:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:00:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码