本仓库的 WebSocket 客户端实现以 Request for Comments 6455(RFC 6455)为依据,目标是帮助理解协议核心流程与帧格式。以下内容基于当前代码状态,描述已实现能力与限制。
- 仅支持明文 WebSocket(
ws),不支持安全 WebSocket(Transport Layer Security,TLS)。 - 握手流程:按 Hypertext Transfer Protocol(HTTP)升级机制发送请求,严格校验
101 Switching Protocols、Upgrade、Connection与Sec-WebSocket-Accept。 - 帧解析(DataFrameParser):解析帧头、长度字段与控制帧约束;服务端帧必须不带掩码(masking),否则视为协议错误。
- 发送帧(DataFrameBuilder):客户端发送必带掩码,支持文本、Ping、Pong、Close 帧;Close 帧可携带状态码与原因文本。
- 关闭流程:收到 Close 帧时解析状态码与原因文本,按规范回发 Close 帧;若解析失败,按协议错误关闭。
- 事件通道:事件流不结束;错误通过事件通知,允许同一实例在
closed后重新connect。
stateChanged:状态变化textReceived:收到文本消息textSent:文本发送成功后派发pingSent:Ping 发送成功后派发errorOccurred:发生错误ping/pong事件目前未派发(收到 Ping 会自动回 Pong,收到 Pong 仅记录日志)
- 不支持分片消息;收到
FIN=0或 continuation 帧即按协议错误关闭(1002)。 - 不支持二进制消息;收到二进制帧按不支持数据关闭(1003)。
- 不支持子协议与扩展;服务端返回相关头会判定失败。
closeImmediately仍未实现。maxMessageSize目前未接入解析器配置(默认 64 KiB)。
下面示例展示一个最小用法:创建客户端、订阅事件、连接与发送文本。
import Combine
import LearnWebSocket
let configuration = WebSocketClientConfiguration(
url: URL(string: "ws://127.0.0.1:8080")!
)
let client = WebSocketClient(configuration: configuration)
var cancellable: AnyCancellable?
cancellable = client.events.sink(
receiveCompletion: { completion in
print("completion: \(completion)")
},
receiveValue: { event in
switch event {
case .stateChanged(let state):
print("state: \(state)")
case .textReceived(let text):
print("text received: \(text)")
case .textSent(let text):
print("text sent: \(text)")
case .pingSent(let data):
print("ping sent: \(data.count) bytes")
case .errorOccurred(let error):
print("error: \(error)")
case .ping, .pong:
break
}
}
)
Task {
try await client.connect()
try await client.send(.text("Hello"))
try await client.sendPing(payload: nil)
try await client.close(code: .normal, reason: "done")
}注意:错误不会结束事件通道;当状态进入 closed 后,可以再次调用 connect() 复用同一实例。