WebSocket 全双工,你可以主动找我,我也可以主动找你。
WebSocket 像是个特立独行的技术,不走寻常路,但偏偏又能解决很多实际问题。
关于WebSocket简单来说,它提供了一种机制,可以让客户端和服务端之间保持一个持久的连接,这样双方就可以实时通信了。
这在以前的 HTTP 世界里几乎是不可能的,因为 HTTP 本质上是一个请求/响应模型,一次请求结束后,连接就会被关闭,下次通信还得重新建立连接。
WebSocket 实现持久连接的的核心技术点在于它的握手过程:
下面我们将围绕这个图进行分析:

刚开始的时候,WebSocket 使用一个类似于 HTTP 的握手请求,这个请求看起来像是普通的 HTTP 请求,但它里面包含了特殊的头部信息,告诉服务器这不是普通的 HTTP 请求,而是希望升级到 WebSocket 协议。
1) Upgrade: 这个头告诉服务器,客户端想要升级当前的连接到 WebSocket 协议。值通常是 websocket。
Upgrade: websocket
2) Connection: 这个头用来指定当前连接应该被升级。值通常是 Upgrade。
Connection: Upgrade
3) Sec-WebSocket-Key: 这是一个随机生成的 Base64 编码的字符串,用于握手验证。服务器需要使用这个键来计算一个特殊的响应值,以确认握手成功。
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
4) Sec-WebSocket-Version: 这个头指定了 WebSocket 协议的版本。目前最常用的版本是 13。
Sec-WebSocket-Version: 13
5) Host: 这个头和普通 HTTP 请求一样,表示请求的目标主机。
6) Origin: 这个头指明了发起请求的页面的来源,即发起 WebSocket 连接的网页地址。
服务器收到这个请求后,如果同意的话,就会发送一个特殊的响应,然后双方就切换到 WebSocket 通道进行通信了。
服务器接收到这个请求后,会检查这些头部信息,并作出相应的响应。响应中同样包含了一些关键头部:
1) Upgrade: 同样是 websocket。
Upgrade: websocket
2) Connection: 同样是 Upgrade。
Connection: Upgrade
3) Sec-WebSocket-Accept: 这个头包含了经过特殊计算后的值,用于验证客户端的 Sec-WebSocket-Key。具体算法是将客户端发送的 Sec-WebSocket-Key 字段加上一个固定的字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11,然后取 SHA-1 哈希,再进行 Base64 编码。
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
握手成功后,连接就升级成了 WebSocket 连接。一旦这个通道打开,双方就可以持续不断地交换数据,直到一方主动断开连接为止。
就是这时候,通信模式就从 HTTP 的请求/响应模式转变成了全双工模式,客户端和服务端可以同时发送数据而不必等待对方回应。
至于为啥 WebSocket 能保持连接不掉线,那是因为它设计了一套心跳机制,每隔一段时间,双方就得发个心跳包,就相当于说:“哥们儿,我还活着呢!”,这样服务器就不会误以为客户端死掉了,就把连接给关了。
这种模式非常适合需要实时交互的应用场景,如在线聊天、股票报价更新、多人游戏等。
这是因为 HTML5 是一个大升级,它引入了很多新的 API 和特性,WebSocket 就是其中之一。
在 HTML4 时代,确实没有 WebSocket 这个东西,那时候要实现类似的功能,开发者们得费老大劲,用各种 hack 技术来模拟持久连接,比如轮询或者长轮询等。这些方法不仅效率低,而且用户体验也不好。
到了 HTML5 时代,WebSocket 成为了标准的一部分,开发者们可以直接使用浏览器提供的 WebSocket API,这大大简化了开发过程。
我想起之前没有那么多丰富的开发框架时,网络编程基本靠纯“手动挡”,一手 TCP,一手 HTTP,两眼一抹黑就开干。
对于普通 Socket(通常指 TCP Socket)是网络编程中的一种基础组件,用于在两台计算机之间建立双向通信连接。它是基于 TCP/IP 协议族中的传输控制协议 (TCP) 实现的,为应用程序提供了一个稳定的、面向连接的数据流服务。
而WebSocket 是一种协议,旨在为 Web 应用程序提供高效、双向的通信通道。它构建于 TCP 协议之上,并利用 HTTP 协议进行握手,之后转换为持久连接,以支持实时数据交换。
在对比区别之前,我们通过实现一个双向通信的过程,先了解下大致过程;
import asyncio
from websockets import serve
async def handle_websocket(websocket, path):
# 接收客户端消息
async for message in websocket:
print(f"Received: {message}")
# 处理消息逻辑
response = process_message(message)
# 向客户端发送响应
await websocket.send(response)
async def main():
# 在指定端口启动 WebSocket 服务器
async with serve(handle_websocket, "localhost", 8765):
print("WebSocket server is running...")
await asyncio.Future() # 运行服务器
if __name__ == "__main__":
asyncio.run(main())
import asyncio
import websockets
async def send_and_receive():
uri = "ws://localhost:8765"
async with websockets.connect(uri) as websocket:
while True:
# 发送消息给服务器
message = input("Enter a message: ")
await websocket.send(message)
# 接收并打印服务器响应
response = await websocket.recv()
print(f"Received: {response}")
if __name__ == "__main__":
asyncio.run(send_and_receive())
import socket
import threading
def handle_client(client_socket, address):
try:
while True:
data = client_socket.recv(1024).decode()
if not data:
break
print(f"Received from {address}: {data}")
response = process_message(data)
client_socket.sendall(response.encode())
finally:
client_socket.close()
def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
print("Server is listening...")
while True:
client_socket, addr = server_socket.accept()
thread = threading.Thread(target=handle_client, args=(client_socket, addr))
thread.start()
if __name__ == "__main__":
start_server()
import socket
def connect_to_server():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))
while True:
message = input("Enter a message: ")
client_socket.sendall(message.encode())
data = client_socket.recv(1024).decode()
if not data:
break
print(f"Received: {data}")
client_socket.close()
if __name__ == "__main__":
connect_to_server()
1、连接建立
2、数据格式
3、通信模式
4、安全性
5、应用范围
以上,点亮【赞与在看】让我们心中充满力量、披荆斩棘、不惧未来!
【推荐阅读】
关于作者:一位热爱技术,并在职场与自媒体间探索的实践者,希望通过分享个人经验和见解,帮助更多人实现自我成长和价值。
如果您对我的公众号内容感兴趣,欢迎关注我。
也可以在下方添加我微信和一支烟花AI社区技术群,一起交流技术、职场心得。
原文作者:皇子谈技术;如有侵权,请联系管理员删除。