You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift调用sendMessage时WebSocket服务器收不到数据无报错求助

问题排查与修复方案

1. URLSession实例被局部创建导致提前释放

在connectToServer(_:)方法中,urlSession是DispatchQueue.main.async闭包内的局部变量,闭包执行完毕后会被ARC自动释放。而socket依赖该URLSession实例存在,后续调用sendMessage(_:)时,socket已失去有效会话上下文,无法正常发送消息。

修复方法:将urlSession改为类属性,确保其生命周期与NetworkKit实例一致:

class NetworkKit: NSObject, ObservableObject, URLSessionWebSocketDelegate {
    private var socket: URLSessionWebSocketTask? = nil
    private var socketHasBeenEstablished = false
    private let logger = Logger(label: "websocket")
    private let operationQueue = OperationQueue()
    private var urlSession: URLSession? // 新增类属性存储URLSession

    func connectToServer(_ address: String) throws {
        logger.info("Connecting to \(address)")
        if let url = URL(string: address) {
            DispatchQueue.main.async {
                let urlRequest = URLRequest(url: url)
                self.urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: self.operationQueue)
                self.socket = self.urlSession?.webSocketTask(with: urlRequest)
                self.socket?.maximumMessageSize = 10_000_0000
                self.socket?.resume()
                
                self.socket?.send(URLSessionWebSocketTask.Message.string("sup world!"), completionHandler: { error in
                    if let error = error {
                        self.logger.error(Logger.Message(stringLiteral: error.localizedDescription))
                    }
                })
            }
        } else {
            throw ConnectionEstablishmentFailedError.InvalidAddress
        }
    }

    // 通过Delegate方法确认连接成功
    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
        socketHasBeenEstablished = true
        logger.info("Connection succeeded: \(socketHasBeenEstablished)")
    }

    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
        socketHasBeenEstablished = false
        logger.info("Connection closed")
    }
}

2. sendMessage方法中completionHandler逻辑反转

当前代码中,completionHandler在error为nil(发送成功)时输出"Unknown error",逻辑完全颠倒,会误导排查方向。

修复方法:修正逻辑并增加连接状态校验:

func sendMessage(_ data: String) throws {
    guard socketHasBeenEstablished else {
        throw ConnectionEstablishmentFailedError.NotConnected // 自定义未连接错误
    }
    logger.info("Sending data: \(data) to websocket server.")
    let message = URLSessionWebSocketTask.Message.string(data)
    DispatchQueue.main.async {
        self.socket?.send(message, completionHandler: { error in
            if let error = error {
                self.logger.error(Logger.Message(stringLiteral: error.localizedDescription))
            } else {
                self.logger.info("Message sent successfully")
            }
        })
    }
}

3. 错误的连接状态标记逻辑

原代码在调用socket?.resume()后立即标记连接成功,但resume()仅启动任务,此时连接未完成握手,后续发送消息可能因连接未就绪失败。

修复方法:通过URLSessionWebSocketDelegate的didOpenWithProtocol方法确认连接成功后,再标记socketHasBeenEstablished为true,同时在sendMessage(_:)中先校验连接状态。

4. sendMessage中重复调用resume()

WebSocketTask首次resume()后即处于活跃状态,重复调用会导致任务状态异常,影响消息发送。

修复方法:删除sendMessage(_:)中的socket?.resume()行。


内容的提问来源于stack exchange,提问作者Praanto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:11:10