ios 开发App连接外部设备WiFi热点,并建立socket通信

开发时在Xcode16.1 ,手机系统版本16.7
需要开启network extension权限、本地网络通信权限

  1. 设置外设热点的ssid和password
    private func connectToWiFi(ssid: String, password: String) {
        if #available(iOS 11.0, *) {
            
            let config = NEHotspotConfiguration(ssid: ssid, passphrase: password, isWEP: false)
            config.joinOnce = true

            NEHotspotConfigurationManager.shared.apply(config) { [weak self] error in
                guard let self = self else { return }
                if let error = error {
                    print("[NetExtHelper] ✗ Failed to connect to WiFi: \(error.localizedDescription)")
                    self.delegate?.helper(self, didFailToConnectWithError: error)
                    self.wifiConnectionCallback?(false, error)
                    self.wifiConnectionCallback = nil
                } else {
                    print("[NetExtHelper] ✓ WiFi connection configured successfully")
                    self.delegate?.helperDidConnectWiFi(self)
                    // 回调成功,让外面继续检查 WiFi 连接状态
                    self.wifiConnectionCallback?(true, nil)
                    self.wifiConnectionCallback = nil
                }
            }
        }
    }
  1. 开启定时器轮询检测App当前连接WiFi状态,确认已连接上外设热点
    func getCurrentWiFiInfo(completion: @escaping WiFiInfoCallback) {
        if #available(iOS 14.0, *) {
            // iOS 14+ uses NEHotspotNetwork
            NEHotspotNetwork.fetchCurrent { network in
                let ssid = network?.ssid
                let bssid = network?.bssid
                print("当前获取到的wifi信息:ssid:\(ssid ?? "null"), bssid:\(bssid ?? "null")")
                completion(ssid, bssid)
            }
        } else {
            // iOS 13 and below use SystemConfiguration
            var ssid: String?
            var bssid: String?

            if let interfaces = CNCopySupportedInterfaces() as? [String] {
                for interface in interfaces {
                    if let info = CNCopyCurrentNetworkInfo(interface as CFString) as? [String: Any] {
                        ssid = info[kCNNetworkInfoKeySSID as String] as? String
                        bssid = info[kCNNetworkInfoKeyBSSID as String] as? String
                        break
                    }
                }
            }

            completion(ssid, bssid)
        }
    }
  1. 开启定时器轮询ping检测外设的socket是否可连接(这一步可选)
    private func performSinglePing(host: String, port: UInt16) {
        pingCheckAttempts += 1

        // Check timeout
        let elapsedTime = Date().timeIntervalSince(pingCheckStartTime ?? Date())
        if elapsedTime >= maxPingTimeout {
            print("[WiFiReachability] ✗ Ping timeout after \(Int(elapsedTime))s")
            print("[WiFiReachability] ✗ Device at \(host):\(port) did not respond after \(pingCheckAttempts) attempts")
            stopPingCheck()
            pingCompletion?(false, WiFiReachabilityError.pingTimeout)
            pingCompletion = nil
            return
        }

        // Attempt socket connection as ping
        testSocket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main)

        do {
            try testSocket?.connect(toHost: host, onPort: port, withTimeout: 10.0)
        } catch {
            // Connection attempt failed, will retry on next timer tick
            let errorCode = (error as? NSError)?.code ?? 0
            let errorDesc = error.localizedDescription

            // Log with more diagnostic info for first few attempts
            if pingCheckAttempts <= 3 || pingCheckAttempts % 10 == 0 {
                print("[WiFiReachability] Ping attempt \(pingCheckAttempts) failed (code: \(errorCode), \(errorDesc), elapsed: \(Int(elapsedTime))s)")
            }
            testSocket?.disconnect()
            testSocket = nil
        }
    }
  1. 建立真正的socket连接
    /// Connect to server
    func connect(host: String? = nil, port: UInt16? = nil) {
        let targetHost = host ?? configuration.serverIP
        let targetPort = port ?? configuration.serverPort

        // Create socket if needed
        if socket == nil {
            socket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main)
        }

        connectionState = .connecting
        receiveBuffer.removeAll()
        currentSequence = 0

        do {
            try socket?.connect(toHost: targetHost, onPort: targetPort, withTimeout: configuration.connectionTimeout)
            print("[WiFi] Connecting to \(targetHost):\(targetPort)")
        } catch {
            print("[WiFi] Connection error: \(error.localizedDescription)")
            let wifiError = WiFiError.connectionFailed(error)
            connectionState = .disconnected
            delegate?.wifiManager(self, didFailToConnectWithError: wifiError)
            connectCallback?(false, wifiError)
            connectCallback = nil
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容