你真的了解WebSocket吗?

本文详细介绍WebSocket的使用方法,包括Python实现服务端与客户端的连接、握手及数据交互过程。此外,还提供了基于Tornado框架的聊天室示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

老男孩教育python学院alex老师总结了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.

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

  View Code

5. 基于Python实现简单示例

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

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

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

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

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

  app.py
  index.html

示例源码下载

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

更多精彩请关注老男孩教育官网:www.oldboyedu.com


<think>嗯,用户想了解WebSocket服务器的概念和它的工作原理,需要一个形象化的理解。首先,我需要回顾一下WebSocket的基础知识。传统上,HTTP协议是无状态的,每次请求都需要重新建立连接,这在实时应用中效率不高。WebSocket的出现解决了这个问题,它允许在客户端和服务器之间建立一个持久化的全双工通信通道。 那WebSocket服务器到底是什么呢?简单来说,它应该是一个能够处理WebSocket协议的服务器,能够维持长连接,实时地发送和接收数据。用户可能需要知道它和普通HTTP服务器的区别,比如如何处理握手过程,如何管理连接状态,以及数据传输的方式。 接下来,形象化的理解部分可能需要比喻。比如,把HTTP比作打电话,每次通话后挂断,而WebSocket就像对讲机,保持一直在线,随时可以通话。这样用户更容易理解两者的差异。 工作原理方面,需要分步骤说明。首先是握手阶段,客户端通过HTTP Upgrade请求升级协议,服务器响应确认,之后连接就保持打开状态。数据帧的传输可能涉及掩码处理,确保安全。这些技术细节需要简化,用通俗的语言解释。 用户可能还关心WebSocket的应用场景,比如在线聊天、实时游戏等,这些例子可以帮助他们理解为什么需要WebSocket服务器。此外,提到的引用内容里有握手请求的例子和客户端连接的代码,可以结合这些引用内容来增强回答的可靠性。 需要注意回答的结构,先定义WebSocket服务器,再解释工作原理,结合比喻和步骤,最后举例应用场景。同时,要确保使用正确的中文表达,避免技术术语过于复杂,让用户容易理解。最后生成的相关问题要围绕服务器实现、协议细节和应用场景展开,帮助用户深入探索。</think>### WebSocket 服务器的概念及工作原理 #### 1. WebSocket 服务器是什么? **WebSocket 服务器**是支持 WebSocket 协议的后端服务,用于与客户端(如浏览器)建立**持久化双向通信**的通道。与传统 HTTP 服务器的“一问一答”模式不同,WebSocket 服务器能在连接建立后主动推送数据,无需客户端频繁发起请求[^1]。 **形象化理解**: - 传统 HTTP:类似“打电话”,每次通话(请求)后挂断,下次需重新拨号。 - WebSocket:类似“对讲机”,连接后双方随时能发送消息,无需反复建立连接。 #### 2. WebSocket 工作原理的简化模型 1. **握手阶段**(HTTP 升级协议) 客户端发送特殊 HTTP 请求(含`Upgrade: websocket`头),服务器验证后返回`101 Switching Protocols`,完成协议升级[^2]。 *示例请求头*: ```http GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== ``` 2. **数据帧传输** 连接建立后,数据通过轻量级的二进制帧(Frame)传输,支持文本、二进制数据。帧格式包含掩码(客户端到服务端需掩码加密)和长度标识。 3. **连接保持与主动推送** 服务器可主动向客户端推送实时数据(如股票价格、游戏状态),客户端也能随时发送请求,实现低延迟交互。 #### 3. 典型应用场景 - **实时聊天**:消息即时到达,无需刷新页面。 - **在线协作工具**:多人同时编辑文档时同步内容。 - **游戏与物联网**:实时传输玩家动作或设备传感器数据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值