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 目录下)

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

!

相同点

•都是基于 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
    Upgrade: websocket. //2
    Connection: Upgrade. //3
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=  //4
    Sec-WebSocket-Protocol: chat. //5

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

收发数据帧:

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

对报文的详细解析过程可以参考文章如下:http://www.cnblogs.com/yjf512/archive/2013/02/18/2915171.html

查看资料:

http://www.jianshu.com/p/59b5594ffbb0

http://www.jianshu.com/p/0e5b946880b4

http://www.jianshu.com/p/f666da1b1835

https://developer.mozilla.org/zh-CN/docs/WebSockets/Writing_WebSocket_servers

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏博客园

WCF系统内置绑定列表与系统绑定所支持的功能

631
来自专栏苦逼的码农

TCP流量控制机制

上篇文章讲了TCP拥塞控制机制的原理,没看过的不妨看下:5分钟读懂拥塞控制,这篇文章讲讲TCP流量控制机制。

932
来自专栏PHP在线

细说WebSocket - Node篇

在上一篇提高到了 web 通信的各种方式,包括 轮询、长连接 以及各种 HTML5 中提到的手段。本文将详细描述 WebSocket协议 在 web通讯 中的实...

2576
来自专栏Linux驱动

IIC接口下的24C02 驱动分析

本节来学习IIC接口下的24C02 驱动分析,本节学完后,再来学习Linux下如何使用IIC操作24C02 1.I2C通信介绍 它是由数据线SDA和时钟SCL构...

1949
来自专栏Golang语言社区

优化Linux的内核参数来提高服务器并发处理能力

PS:在服务器硬件资源额定有限的情况下,最大的压榨服务器的性能,提高服务器的并发处理能力,是很多运维技术人员思考的问题。要提高Linux系统下的负载能力,可以使...

2204
来自专栏张善友的专栏

TCP - WAIT状态及其对繁忙的服务器的影响

TCP有一个TIME—WAIT状态.通常有2分钟。在一个繁忙的网站,2分钟常常有数千个访问请求.假设服务器A的处理能力比B大两倍,但服务器A有数千个TIME~w...

2345
来自专栏Golang语言社区

【Go 语言社区】一个WebSocket的简单Echo例子

一个WebSocket的简单Echo例子:例子代码来自:http://www.websocket.org/echo.html 使用一个文本编辑器,把下面代码复制...

2747
来自专栏任浩强的运维生涯

优化内核参数提高服务器的并发处理能力

PS:在服务器硬件资源额定有限的情况下,最大的压榨服务器的性能,提高服务器的并发处理能力,是很多运维技术人员思考的问题。要提高Linux系统下的负载能力,可以使...

4118
来自专栏IT技术精选文摘

关于TCP 半连接队列和全连接队列

最近碰到一个client端连接异常问题,然后定位分析并查阅各种资料文章,对TCP连接队列有个深入的理解 查资料过程中发现没有文章把这两个队列以及怎么观察他们的指...

2609
来自专栏知识分享

关于TCP和MQTT之间的转换

可以看这个,本来我自己想用Wireshark监听一下,不过百度一搜索一大把,我就不测试了

942

扫码关注云+社区