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 条评论
登录 后参与评论

相关文章

来自专栏苍云横渡学习笔记

【Docker学习笔记(二)】镜像、容器数据卷

镜像是一种轻量级、可执行的独立软件包,用来打包 软件运行环境 和 基于运行环境开发的软件。它包含某个软件所需的所有内容,包括代码、运行时环境、库、环境变量和配置...

614
来自专栏java一日一条

浏览器与服务器的消息通信

最近工作中遇到一个场景,商家在商家后台需要实时的获取到有没有新订单,有的话是几个;这个需求类似与日常中使用QQ或者微信时的新信息提醒一样,只要有新信息就需要提醒...

693
来自专栏散尽浮华

nginx的web缓存服务环境部署记录

web缓存位于内容源Web服务器和客户端之间,当用户访问一个URL时,Web缓存服务器会去后端Web源服务器取回要输出的内容,然后,当下一个请求到来时,如果访问...

3097
来自专栏漫漫全栈路

Docker 初次见面

Docker没有官方中文文档(至少目前为止没有,2018/1/1),所以只能通过搜索引擎加上我自己的了解来说一下。

3708
来自专栏JavaWeb

Web服务器加速之Tomcat7性能如何调优

3686
来自专栏前端架构

WebSocket的JavaScript例子

在HTML5规范中,我最喜欢的Web技术就是正迅速变得流行的WebSocket API。WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的A...

982
来自专栏HappenLee的技术杂谈

LVS-NAT模式的配置详解

由于实验室拟态存储的项目需要通过NAT模式来映射NFS服务器已实现负载均衡的目的,通过调研了多种负载均衡机制,笔者最终选择了LVS的NAT模式来实现需求,接下来...

723
来自专栏快乐八哥

使用Docker-Docker for Web Developers(2)

1. 使用镜像 1.1 在Docker Hub上查找镜像 我们查找一下之前博客里面,推送到Docker Hub里面的bage88/docker-demo,能看到...

17710
来自专栏服务端技术杂谈

Motan源码阅读--工程概述

负载均衡默认为activeWeight,低并发度优先,refer的某个时刻call的数量越小优先级越高。

794
来自专栏阮一峰的网络日志

HTTP 协议入门

HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。 本文介绍 HTTP 协议的历史演变和设计思路。 ? 一...

33111

扫码关注云+社区