首先明确几点:

1.  websocket是一种协议。是html5的一种新协议;
2. 与http的区别是,它是一种双向通信协议,服务器和客户端都能主动向对方发送或接受数据;
3. websocket需要进行握手连接之后才能进行通信;

由此我们便知道了websocket诞生的意义:

传统的HTTP请求方式,是客户端发送请求服务端响应的形式,这种方式在应对信息变化不是很频繁的应用时还能较好的应对,但是对于实时要求/海量并发的应用来说显得不是很给力,尤其在当前业界移动的互联网蓬勃发展的趋势下,高并发与用户实时响应是web应用经常面临的问题,比如金融证券的实时信息,web导航应用中的地理位置获取,社交网络的实时消息推送等.

基于HTTP,我们也有实时通讯的方案,比如轮询,比如使用flash的socket,但是这些都是非标准的,而且代价较大,HTML5的标准化组织需要针对实时通讯的应用场景提供一套业界同意的规范,那就是websocket.

socket通信方式

socket的概念最初出现在linux网络编程中,socket是在应用层和传输层之间的一个抽象层,他把TCP连接建立和释放的过程惊醒了一层封装,提供出接口给应用层.

socket是如何与对应网络中的进程进行通信的呢?

我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这是后我们需要另辟蹊径了,我们知道ip层的IP地址可以唯一标示主机,而TCP层协议和端口可以唯一标示一个进程,这样我们可以利用IP地址+协议+端口号唯一标示网络中的一个进程.

那么在进行socket接口调用了时候,传递上述唯一标示之后,生成响应的协议请求,双向通信就能通过socket进行了.

websocket的作用也是模仿socket的通信能力,但是不同的是,它本身是一种协议,浏览器和服务端会对这种协议进行解析,他是基于基础TCP连接的,所以本身它是具有建立双向连接的能力的,只不过具体的数据传输方式和一些针对web实时通讯的特性需要在websocket中进行定义.

websocket简介

传统的HTTP请求方式:

websocket的通信方式

可以看到,HTTP请求每次与服务端交互一定的重新建立连接,但是websocket协议之需要双方通过握手建立连接,在连接释放之前,客户端和服务端可以相互接受和传递数据,因为双方通过协议是知道建立websocket连接各自进程的端口号.

在客户端中,我们需要使用websocket对象,去连接ws://这样的服务端url,这样客户端就会自动解析并识别websocket请求从而和服务端通过握手建立连接.

websocket客户端连接报文

GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://localhost:8080
Sec-WebSocket-Version: 13

其中,"Sec-WebSocket-Key"是websocket客户端发送的一个base64编码的密文,要求服务端必须返回一个对应加密的"Sec-Socket-Accept"应答,否则客户端会抛出"Error during WebSocket handshake"错误,并关闭连接.

websocket服务端响应报文

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

"Sec-WebSocket-Accept"的值是服务端采用与客户端一直的秘钥计算出来后返回客户端的,"HTTP/1.1 101 Switching Protocols"表示服务端接受WebSocket连接握手成功,后续就可以进行TCP通讯了.

websocket的实现

要实现websocket,必须客户端和服务端都要支持这个协议.

Tomcat在新版本中提供了WebSocketServle对象,用于支持websocket,php肯定也有自己的websocket封装.

而在客户端HTML5提佛那个了标准的websocket API ,demo实现如下:

var ws = new WebSocket(“ws://echo.websocket.org”);
ws.onopen = function(){ws.send(“Test!”); };
ws.onmessage = function(evt){console.log(evt.data);ws.close();};
ws.onclose = function(evt){console.log(“WebSocketClosed!”);};
ws.onerror = function(evt){console.log(“WebSocketError!”);};
ws.send("hello");//向服务器发送消息

第一行代码是在申请一个websocket对象,参数是需要连接的服务器端的地址,同HTTP协议开头一样,websocket协议的url使用ws://开头,另外安全的websocket协议使用ws://开头

第二行到第五行为websocket对象注册消息的处理函数,websocket对象一共支持四个消息 onopen, onmessage, onclose, onerror,有了这四个事件,我们就可以很容易很轻松驾驭websocket.

当Browser和websocketserver连接成功后,会触发onopen消息,如果连接失败,发送.接收数据失败或者处理数据出现错误,browser会触发onerror消息;当browser接收到websocketserver发送过来的数据时,就会触发onmessage消息,参数evt中包含server传输过来的数据;当browser接收到websocket端发送的关闭连接请求时,就触发onclose消息,我们可以看出所有的操作都是采用一步回调的方法触发,这样不会阻塞UI,可以获得更快的响应时间,更好的用户体验.

websocket的加密与解密

加密:

import struct
msg_bytes = "the emperor has not been half-baked in the early days of the collapse of the road, today down three points, yizhou weakness, this serious crisis autumn".encode("utf8")
token = b"\x81" # + 数据长度/运算位 + mask/数据长度 + mask/数据 + 数据
length = len(msg_bytes) if length < 126:
token += struct.pack("B", length)
elif length == 126:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length) msg = token + msg_bytes print(msg)

解密:

#b'\x81\x89\xf3\x99\x81-\x15\x05\x01\xcbO\x1be\x97]'
#b'\x81\x85s\x92a\x10\x1b\xf7\r|\x1c'
#b'\x81\x83H\xc0x\xa6y\xf2K' hashstr = b'\x81\x85s\x92a\x10\x1b\xf7\r|\x1c'
# b'\x81 \x85s \x92a\x10\x1b\xf7 \r|\x1c' <126
# \x85s = 5
# print(chushibiao[1],chushibiao[1]&127)
# print(chushibiao[2:4],chushibiao[4:8])
# 将第二个字节也就是 \x83 第9-16位 进行与127进行位运算
payload = hashstr[1] & 127
print(payload)
if payload == 127:
extend_payload_len = hashstr[2:10]
mask = hashstr[10:14]
decoded = hashstr[14:]
# 当位运算结果等于127时,则第3-10个字节为数据长度
# 第11-14字节为mask 解密所需字符串
# 则数据为第15字节至结尾 if payload == 126:
extend_payload_len = hashstr[2:4]
mask = hashstr[4:8]
decoded = hashstr[8:]
# 当位运算结果等于126时,则第3-4个字节为数据长度
# 第5-8字节为mask 解密所需字符串
# 则数据为第9字节至结尾 if payload <= 125:
extend_payload_len = None
mask = hashstr[2:6]
decoded = hashstr[6:] # 当位运算结果小于等于125时,则这个数字就是数据的长度
# 第3-6字节为mask 解密所需字符串
# 则数据为第7字节至结尾 str_byte = bytearray()
# b'\x81 \x85s \x92a\x10\x1b \xf7\r|\x1c' <126
for i in range(len(decoded)): # 0 \xf7 ^ \x92a 1 \r ^ \x10 \x1c ^ \x1b
byte = decoded[i] ^ mask[i % 4]
str_byte.append(byte) print(str_byte.decode("utf8"))

websocket的原理的更多相关文章

  1. WebSocket的原理,以及和Http的关系

    一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...

  2. WebSocket的原理,以及和Http的关系 (转载)

    一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...

  3. WebSocket协议-原理篇

    本篇文章主要讲述以下几点: WebSocket的原理与机制 WebSocket与Socket.io WebSocket兼容性 WebSocket的原理与机制 WebSocket协议分为两部分:握手和数 ...

  4. nginx支持websocket及websocket部分原理介绍

    nginx支持websocket及websocket部分原理介绍最近ipc通过websocket与server进行通行,经过无法通过nginx进行反向代理,只有直连nodejs端口.而且部署到阿里云用 ...

  5. Websocket(一)——原理及基本属性和方法

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处? 答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起. 举例 ...

  6. WebSocket的原理与优缺点

    websocket 是长连接,受网络限制比较大,需要处理好重连,比如用户进电梯或电信用户打个电话网断了,这时候就需要重连,如果 ws 一直重连不上,有些较复杂的业务方会不愿意的,是不是还要搞个 htt ...

  7. (转)WebSocket的原理

    前言:无聊逛知乎,就逛到H5的栏目去了,正好看到了关于Websocket的东西.个人是比较喜欢看这类风格的,转到博客分享,以便自己以后理解. ---------------------分割线----- ...

  8. 分析HTML5中WebSocket的原理

    目录结构   一.什么是Websocket websocket是html5提出的一个协议规范,参考rfc6455. 不过目前还都是在草案,没有成为标准,毕竟html5还在路上. websocket约定 ...

  9. 一文带你看懂WebSocket 的原理?为什么可以实现持久连接?

    工作之余在知乎上偶然看到一篇回帖,瞬间觉得之前看的那么多资料都不及这一篇让我对 websocket 的认知深刻易懂,之前看总完总觉得一知半解云里雾里.所以与大家共同分享一下一起学习.比较喜欢这种博客理 ...

  10. 【计算机网络】WebSocket实现原理分析

    1.介绍一下websocket和通信过程? 1.1 基本概念 [!NOTE] Websocket是应用层第七层上的一个应用层协议,它必须依赖 HTTP 协议进行一次握手 ,握手成功后,数据就直接从 T ...

随机推荐

  1. 使用pycharm学习django纪实

    之前已经下了python3.7 首先官网下载pycharm专业版,然后利用学生邮箱激活 新建django项目,使用虚拟环境就好了,方便之后的服务器部署(大概 找到博客开始学习:https://blog ...

  2. JavaSE 学习笔记之集合框架(十八)

    集合框架:,用于存储数据的容器. 特点: 1:对象封装数据,对象多了也需要存储.集合用于存储对象. 2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合.因为集合是可变长度的. 集合和数组的区 ...

  3. 重载与重写的区别----https://blog.csdn.net/zhu_apollo/article/details/1852542

    重载 overloading        1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型.重载是一个类中多态性的一种表现.        ...

  4. hdu 5040bfs+优先队列 需要存状态

    /* 剪枝:四秒后状态会变得和原来一样,所以四秒后如果再经过这个点肯定不是最优的舍去 易错点:在一个是从.到.这两个点都没有被照到并且不是摄像机,也可能需要等3秒,因为后面的结果可能再这三秒中发生改变 ...

  5. [bzoj2440]完全平方数[中山市选2011][莫比乌斯函数][线性筛][二分答案]

    题意:求第k个分解质因子后质因子次数均为一的数,即求第k个无平方因子数. 题解: 首先二分答案mid,那么现在就是要求出mid以内的无平方因子数的个数. 其次枚举$\sqrt{mid}$内的所有质数, ...

  6. PatentTips - Hamming distance comparison

    BACKGROUND INFORMATION In a typical data processing environment, data may be transmitted in multiple ...

  7. Java虚拟机深入JVM内核—原理、诊断与优化视频教程

    http://www.eimhe.com/forum.php?mod=viewthread&tid=142832&highlight=%C4%DA%BA%CB

  8. Oracle Multitenant Environment (二) Purpose

    Purpose of a Multitenant Environment A multitenant environment enables the central management of mul ...

  9. Lein: Exception in thread "Thread-3" java.net.ConnectException: Connection refused

    leiningen Leiningen是你的主要工具, 它用于: 启动一个 REPL 下载+安装类库 运行你的程序 启动一个服务器, 运行你所写的webapps 安装 brew install lei ...

  10. C++学习之可变参数的函数与模板

    所谓可变参数指的是函数的参数个数可变,参数类型不定的函数.为了编写能处理不同数量实参的函数,C++11提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为initializer_list的标 ...