首页 编程 软件学院 查看内容

Websocket 基础篇

2017-5-31 14:25 |来自: 互联网 2094 0

摘要: 一、理解 socket , tcp , websocket, http 的联系和区别socketsocket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定sock ...

一、理解 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 目录下)

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

网络中的 socekt:

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

websocket

先看网络协议图:

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

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

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 消息对,仍然会造成资源的浪费、实时性不强等问题。

!

相同点

�6�1都是基于 TCP 的应用层协议

�6�1都使用 Request/Response 模型进行连接的建立

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

�6�1都可以在网络中传输数据

不同点

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

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

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

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

�6�1WS 的数据帧有序

二、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:)

收发数据帧:

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

本文出处: http://www.toutiao.com/a6419594345925853441/
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部