Skip to content

SunsetWan/WebSocketClient-Demo

Repository files navigation

WebSocketClient 当前实现说明

本仓库的 WebSocket 客户端实现以 Request for Comments 6455(RFC 6455)为依据,目标是帮助理解协议核心流程与帧格式。以下内容基于当前代码状态,描述已实现能力与限制。

已实现功能

  • 仅支持明文 WebSocket(ws),不支持安全 WebSocket(Transport Layer Security,TLS)。
  • 握手流程:按 Hypertext Transfer Protocol(HTTP)升级机制发送请求,严格校验 101 Switching ProtocolsUpgradeConnectionSec-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() 复用同一实例。

参考

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages