WebSocket与实时通讯技术
发布时间: 2023-12-16 04:03:52 阅读量: 18 订阅数: 15
# 一、WebSocket简介
## 1.1 传统通讯方式的局限性
传统的HTTP通信协议使用的是"请求-响应"模式,即客户端发送请求,服务器响应请求,这种方式在实时通讯场景下存在一定的局限性。例如,聊天应用中需要频繁地向服务器发送请求来获取新消息,这种轮询的方式既浪费了带宽又增加了服务器的负载。此外,HTTP协议不支持服务器主动向客户端发送消息,需要客户端不断地发送请求才能获取消息,效率低下。
## 1.2 WebSocket的定义与特点
WebSocket是一种全双工通信协议,允许客户端和服务器之间进行实时的双向通讯。它基于HTTP协议,但是与HTTP有所不同,WebSocket客户端与服务器只需要进行一次握手,之后就可以通过建立的连接进行双向通讯,不再需要发送多余的HTTP请求。相比于传统的HTTP通信,WebSocket具有实时性好、效率高、数据传输量小等特点。
## 1.3 WebSocket与HTTP/HTTPS的对比
- 连接方式:HTTP协议使用"请求-响应"模式,需要客户端发送请求,服务器响应请求。而WebSocket通过一次握手后建立连接,客户端和服务器可以进行双向通信。
- 数据传输量:由于不需要频繁地发送HTTP请求,WebSocket的数据传输量相对较小,减少了网络负载。
- 实时性:WebSocket的实时性较好,可以实时地推送消息给客户端,而HTTP协议需要客户端不断发送请求来获取新数据。
### 二、WebSocket的工作原理
#### 2.1 握手过程
WebSocket的握手过程与HTTP的握手过程类似,但存在一些细微的差别。下面是WebSocket握手的具体步骤:
1. 客户端发送HTTP请求到服务器,请求中包含Upgrade字段,表明客户端希望升级协议为WebSocket。
2. 服务器收到请求后,进行判断是否支持WebSocket协议。如果支持,则生成随机的WebSocket协议版本号,并返回响应。
3. 客户端收到响应后,进行验证服务器返回的状态码以及协议版本号是否匹配。如果匹配,则客户端认可服务器的WebSocket支持。
4. 合法的握手完成后,双方可以通过WebSocket进行实时通讯。
以下是一段用Python实现WebSocket握手的示例代码:
```python
import socket
import base64
import hashlib
# WebSocket握手
def handshake(client_socket):
# 读取客户端的请求数据
request_bytes = client_socket.recv(1024)
request = request_bytes.decode()
# 获取Sec-WebSocket-Key字段的值
key = ''
for line in request.split('\r\n'):
if 'Sec-WebSocket-Key' in line:
key = line.split(':')[1].strip()
# 生成响应的Sec-WebSocket-Accept字段的值
magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
accept_key = base64.b64encode(hashlib.sha1((key + magic_string).encode()).digest()).decode()
# 构造响应
response = "HTTP/1.1 101 Switching Protocols\r\n"
response += "Upgrade: websocket\r\n"
response += "Connection: Upgrade\r\n"
response += "Sec-WebSocket-Accept: " + accept_key + "\r\n\r\n"
# 发送响应到客户端
client_socket.send(response.encode())
# 创建socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)
while True:
# 等待客户端连接
print('Waiting for connection...')
client_socket, address = server_socket.accept()
print('Connected with', address)
# 进行握手
handshake(client_socket)
# 后续处理...
```
上述代码中,通过创建一个服务器socket对象,并监听8000端口。当有客户端连接时,会进行WebSocket的握手过程。握手过程中,服务器会读取客户端的握手请求,并生成响应数据返回给客户端,完成握手。
#### 2.2 数据传输方式
WebSocket支持全双工、双向通信,可以实现服务器主动向客户端推送消息。数据传输过程中,采用帧(Frame)的方式进行。
每个WebSocket帧由多个字节组成,包含以下几个部分:
- **Fin(1 bit)**:表示是否是消息的最后一个帧。
- **Opcode(4 bits)**:标识数据的类型,常用的有文本(Text)帧和二进制(Binary)帧。
- **Mask(1 bit)**:用于掩码处理,WebSocket规定客户端发送的帧必须进行掩码处理。
- **Payload length(7 bits或7 + 16 bits或7 + 64 bits)**:标识负载数据的长度。
- **Masking key(0或4 bytes)**:只有在Mask为1时才存在,用于解码负载数据。
- **Payload data(变长)**:存储实际的负载数据。
以下是一段用Python实现发送WebSocket文本帧的示例代码:
```python
import struct
import socket
def send_text_message(client_socket, message):
message = message.encode()
header = b'\x81'
payload_length = len(message)
if payload_length <= 125:
header += struct.pack('!B', payload_length)
elif 126 <= payload_length <= 65535:
header += b'\x7e' + struct.pack('!H', payload_length)
else:
header += b'\x7f' + struct.pack('!Q', payload_length)
data = header + message
client_socket.send(data)
# 创建socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 8000))
while True:
message = input('Please enter mes
```
0
0