Websocket 基础篇

IT知识
534
0
0
2022-07-10
标签   websocket

Websocket 基础篇

一、理解 socket , tcp , websocket, http 的联系和区别

socket

socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口

一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定

socket 起源于 Unix,而 Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开 open –> 读写 write/read –> 关闭 close”模式来操作。socket 即是一种特殊的文件,一些 socket 函数就是对其进行的操作(读/写 IO、打开、关闭)

Unix 中的 Socket,读起来太抽象,打个具体的比方吧,我们的消息队列文件就是 s 类型的文件,就是 socket 文件:(appplatform 框架下消息队列文件存在/tmp/app 目录下)

Websocket 基础篇

ps:appplatfrom 里面配的两个 MsgQKey 在 ServiceConfig.xml 文件中配置的,成对出现可以在这里查到。27e5→27e50(加个 0)→163408(再换成十进制)。。。扯远了。

Websocket 基础篇

网络中的 socekt:

在本地可以通过进程 PID 来唯一标识一个进程,但是在网络中这是行不通的。其实 TCP/IP 协议族已经帮我们解决了这个问题,网络层的“ip 地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip 地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

websocket

先看网络协议图:

Websocket 基础篇

就是说 Websocket 是应用层协议的一种,建立在 http 协议之上,它的诞生是为了创建一种「双向通信」的协议,来作为 HTTP 协议的一个替代者。

情不自禁要问,为什么要用 WebSocket 来替代 HTTP?Http 也有 Keep-Alive,如图随便抓个 http 的包都能看到 Keep-Alive。

Websocket 基础篇

HTTP1.1 默认使用持久连接(persistent connection),在一个 TCP 连接上也可以传输多个 Request/Response 消息对,但是 HTTP 的基本模型还是一个 Request 对应一个 Response。这在双向通信(客户端要向服务器传送数据,同时服务器也需要实时的向客户端传送信息,一个聊天系统就是典型的双向通信)时一般会使用这样几种解决方案:

  1. 轮询(polling),轮询就会造成对网络和通信双方的资源的浪费,且非实时。
  2. 长轮询,客户端发送一个超时时间很长的 Request,服务器 hold 住这个连接,在有新数据到达时返回 Response,相比#1,占用的网络带宽少了,其他类似。
  3. 长连接,其实有些人对长连接的概念是模糊不清的,我这里讲的其实是 HTTP 的长连接(1)。如果你使用 Socket 来建立 TCP 的长连接(2),那么,这个长连接(2)跟我们这里要讨论的 WebSocket 是一样的,实际上 TCP 长连接就是 WebSocket 的基础,但是如果是 HTTP 的长连接,本质上还是 Request/Response 消息对,仍然会造成资源的浪费、实时性不强等问题。

Websocket 基础篇

!

相同点

•都是基于 TCP 的应用层协议

•都使用 Request/Response 模型进行连接的建立

•在连接的建立过程中对错误的处理方式相同,在这个阶段 WS 可能返回和 HTTP 相同的返回码

•都可以在网络中传输数据

不同点

•WS 使用 HTTP 来建立连接,但是定义了一系列新的 header 域,这些域在 HTTP 中并不会使用

•WS 的连接不能通过中间人来转发,它必须是一个直接连接

•WS 连接建立之后,通信双方都可以在任何时刻向另一方发送数据

•WS 连接建立之后,数据的传输使用帧来传递,不再需要 Request 消息

•WS 的数据帧有序

二、websocket 握手

出于兼容性的考虑,WS 的握手使用 HTTP 来实现,客户端的握手消息就是一个「普通的,带有 Upgrade 头的,HTTP Request 消息」。所以这一个小节到内容大部分都来自于 RFC2616,这里只是它的一种应用形式,下面是 RFC6455 文档中给出的一个客户端握手消息示例:

 GET /chat HTTP/1.1 //1
 Host: server.example.com //2
 Upgrade: websocket //3
 Connection: Upgrade //4
 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== //5
 Origin: http://example.com //6
 Sec-WebSocket-Protocol: chat, superchat //7
 Sec-WebSocket-Version: 13 //8

可以看到,前两行跟 HTTP 的 Request 的起始行一模一样,而真正在 WS 的握手过程中起到作用的是下面几个 header 域。

  1. Upgrade:upgrade 是 HTTP1.1 中用于定义转换协议的 header 域。它表示,如果服务器支持的话,客户端希望使用现有的「网络层」已经建立好的这个「连接(此处是 TCP 连接)」,切换到另外一个「应用层」(此处是 WebSocket)协议。
  2. Connection:HTTP1.1 中规定 Upgrade 只能应用在「直接连接」中,所以带有 Upgrade 头的 HTTP1.1 消息必须含有 Connection 头,因为 Connection 头的意义就是,任何接收到此消息的人(往往是代理服务器)都要在转发此消息之前处理掉 Connection 中指定的域(不转发 Upgrade 域)。

如果客户端和服务器之间是通过代理连接的,那么在发送这个握手消息之前首先要发送 CONNECT 消息来建立直接连接。

  1. Sec-WebSocket-*:第 7 行标识了客户端支持的子协议的列表(关于子协议会在下面介绍),第 8 行标识了客户端支持的 WS 协议的版本列表,第 5 行用来发送给服务器使用(服务器会使用此字段组装成另一个 key 值放在握手返回信息里发送客户端)。
  2. Origin:作安全使用,防止跨站攻击,浏览器一般会使用这个来标识原始域。

如果服务器接受了这个请求,可能会发送如下这样的返回信息,这是一个标准的 HTTP 的 Response 消息。101 表示服务器收到了客户端切换协议的请求,并且同意切换到此协议。RFC2616 规定只有 HTTP1.1 及 HHTTP1.1 以上版本的时候才能同意切换。

 HTTP/1.1 101 Switching Protocols //1

ws 协议默认使用 80 端口,wss 协议默认使用 443 端口。(和 http 一样啊:relaxed:)

收发数据帧:

客户端和服务端都能在任意时候发送数据,(不管是从客户端到服务端还是相反) 每个数据帧的格式都是:

Websocket 基础篇