你真的了解WebSocket吗?

老男孩IT教育python高级讲师武Sir一篇文章带你了解WebSocket的真正应用方法:

WebSocket协议是基于TCP的一种新的协议。WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符。它实现了浏览器与服务器全双工(full-duplex)通信。其本质是保持TCP连接,在浏览器和服务端通过Socket进行通信。

本文将使用Python编写Socket服务端,一步一步分析请求过程!!!

1. 启动服务端


1

2

3

4

5

6

7

8

9

10


import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind((‘127.0.0.1‘8002))

sock.listen(5)

# 等待用户连接

conn, address = sock.accept()

...

...

...

启动Socket服务器后,等待用户【连接】,然后进行收发数据。

2. 客户端连接


1

2

3

4


<script type="text/javascript">

    var socket = new WebSocket("ws://127.0.0.1:8002/xxoo");

    ...

</script>

当客户端向服务端发送连接请求时,不仅连接还会发送【握手】信息,并等待服务端响应,至此连接才创建成功!

3. 建立连接【握手】


1

2

3

4

5

6

7

8

9

10

11

12

13

14


import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind((‘127.0.0.1‘8002))

sock.listen(5)

# 获取客户端socket对象

conn, address = sock.accept()

# 获取客户端的【握手】信息

data = conn.recv(1024)

...

...

...

conn.send(‘响应【握手】信息‘)

请求和响应的【握手】信息需要遵循规则:

  • 从请求【握手】信息中提取 Sec-WebSocket-Key
  • 利用magic_string 和 Sec-WebSocket-Key 进行hmac1加密,再进行base64加密
  • 将加密结果响应给客户端

注:magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11

请求【握手】信息为:

+

提取Sec-WebSocket-Key值并加密:

+

4.客户端和服务端收发数据

客户端和服务端传输数据时,需要对数据进行【封包】和【解包】。客户端的JavaScript类库已经封装【封包】和【解包】过程,但Socket服务端需要手动实现。

第一步:获取客户端发送的数据【解包】

 基于Python实现解包过程(未实现长内容)

解包详细过程:

+

The MASK bit simply tells whether the message is encoded. Messages from the client must be masked, so your server should expect this to be 1. (In fact, section 5.1 of the spec says that your server must disconnect from a client if that client sends an unmasked message.) When sending a frame back to the client, do not mask it and do not set the mask bit. We‘ll explain masking later. Note: You have to mask messages even when using a secure socket.RSV1-3 can be ignored, they are for extensions.

The opcode field defines how to interpret the payload data: 0x0 for continuation, 0x1 for text (which is always encoded in UTF-8), 0x2 for binary, and other so-called "control codes" that will be discussed later. In this version of WebSockets, 0x3 to 0x7 and 0xB to 0xF have no meaning.

The FIN bit tells whether this is the last message in a series. If it‘s 0, then the server will keep listening for more parts of the message; otherwise, the server should consider the message delivered. More on this later.

Decoding Payload Length

To read the payload data, you must know when to stop reading. That‘s why the payload length is important to know. Unfortunately, this is somewhat complicated. To read it, follow these steps:

  1. Read bits 9-15 (inclusive) and interpret that as an unsigned integer. If it‘s 125 or less, then that‘s the length; you‘re done. If it‘s 126, go to step 2. If it‘s 127, go to step 3.
  2. Read the next 16 bits and interpret those as an unsigned integer. You‘re done.
  3. Read the next 64 bits and interpret those as an unsigned integer (The most significant bit MUST be 0). You‘re done.

Reading and Unmasking the Data

If the MASK bit was set (and it should be, for client-to-server messages), read the next 4 octets (32 bits); this is the masking key. Once the payload length and masking key is decoded, you can go ahead and read that number of bytes from the socket. Let‘s call the data ENCODED, and the key MASK. To get DECODED, loop through the octets (bytes a.k.a. characters for text data) of ENCODED and XOR the octet with the (i modulo 4)th octet of MASK. In pseudo-code (that happens to be valid JavaScript):

var DECODED = "";
for (var i = 0; i < ENCODED.length; i++) {
    DECODED[i] = ENCODED[i] ^ MASK[i % 4];
}

Now you can figure out what DECODED means depending on your application.

第二步:向客户端发送数据【封包】

 

5. 基于Python实现简单示例

a. 基于Python socket实现的WebSocket服务端:

+

b. 利用JavaScript类库实现客户端

+

6. 基于Tornado框架实现Web聊天室

Tornado是一个支持WebSocket的优秀框架,其内部原理正如1~5步骤描述,当然Tornado内部封装功能更加完整。

以下是基于Tornado实现的聊天室示例:

 app.py

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>Python聊天室</title></head><body>
    <div>
        <input type="text" id="txt"/>
        <input type="button" id="btn" value="提交" onclick="sendMsg();"/>
        <input type="button" id="close" value="关闭连接" onclick="closeConn();"/>
    </div>
    <div id="container" style="border: 1px solid #dddddd;margin: 20px;min-height: 500px;">

    </div>

    <script src="/static/jquery-2.1.4.min.js"></script>
    <script type="text/javascript">
        $(function () {
            wsUpdater.start();
        });        var wsUpdater = {
            socket: null,
            uid: null,
            start: function() {                var url = "ws://127.0.0.1:8888/chat";
                wsUpdater.socket = new WebSocket(url);
                wsUpdater.socket.onmessage = function(event) {
                    console.log(event);                    if(wsUpdater.uid){
                        wsUpdater.showMessage(event.data);
                    }else{
                        wsUpdater.uid = event.data;
                    }
                }
            },
            showMessage: function(content) {
                $(‘#container‘).append(content);
            }
        };        function sendMsg() {            var msg = {
                uid: wsUpdater.uid,
                message: $("#txt").val()
            };
            wsUpdater.socket.send(JSON.stringify(msg));
        }</script></body></html>

示例源码下载

参考文献:https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

更多精彩请关注:老男孩python培训

时间: 2024-10-20 07:51:19

你真的了解WebSocket吗?的相关文章

web新特性 之 WebSocket

详情参见:你真的了解WebSocket吗?     WebSocket系列教程   HTML5新特性之WebSocket WebSocket协议是基于TCP的一种新的协议.WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符.它实现了浏览器与服务器全双工(full-duplex)通信.其本质是保持TCP连接,在浏览器和服务端通过Socket进行通信. 服务端与客户端的连接不断开,实现全双工的操作.及服务端或是客户端都会给对方发送消息. WebSocke

WebSocket 是什么原理?为什么可以实现持久连接?

著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Ovear链接:http://www.zhihu.com/question/20215561/answer/40316953来源:知乎 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟

看完让你彻底搞懂Websocket原理

偶然在知乎上看到一篇回帖,瞬间觉得之前看的那么多资料都不及这一篇回帖让我对 websocket 的认识深刻有木有.所以转到我博客里,分享一下.比较喜欢看这种博客,读起来很轻松,不枯燥,没有布道师的阵仗,纯粹为分享.废话这么多了,最后再赞一个~ 一.websocket与http WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-aliv

websocket 概述

WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex). [[ from websocket是什么原理? ]] 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是

WebSocket 是什么原理?为什么可以实现持久连接?(转载)

本文转载自知乎,来源如下: 作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Webs

Websocket原理

一.websocket与http WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP请求合并为一个,但是 Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充可以通过这样一张图理解 有交集,但是并不是全部. 另外html

WebSocket能干啥

------这东西到底有什么用途,仔细看了说明,还是不明所以.楼上几位能不能介绍一下实际使用的场景?? 1.可以实现 服务器端(delphi&[email protected])<->手机端 ssl加密通讯&用户认证 2.可以实现 服务器端(delphi&[email protected])<->手机端 消息推送 3.可以实现 服务器端(delphi&[email protected])<->手机端 数据集(json)互传4.可以实现 服

WebSocket///////////////////////z

作者:Ovear链接:http://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有,转载请联系作者获得授权. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,

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

一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. Http协议本身只有1.0和1.1,也就是所谓的Keep-alive,把多个Http请求合并为一个. 二.WebSocket是什么样的协议,具体有什么优点. 首先,相对于Http这种非持久的协议来说,WebSocket是一种持久化的协议. 举例说明: (1)Http的生命周期通过Request来界