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

如何在Swift 2中从TCP套接字读取自定义二进制流式数据?

Swift 2读取自定义二进制流数据方案

当然可以只发送二进制数据!你的用例里,两个非零8位值加0字节分隔的格式简单清晰,很适合这种每秒1-2次的小数据传输场景。下面是一套完整的Swift 2实现代码,包含TCP连接建立、异步数据读取和格式解析逻辑:

核心实现类

import Foundation

class BinaryDataReader: NSObject, NSStreamDelegate {
    private var inputStream: NSInputStream?
    private var dataBuffer = NSMutableData()
    
    /// 连接到指定服务器和端口
    func connectToServer(host: String, port: Int) {
        var readStream: Unmanaged<CFReadStream>?
        var writeStream: Unmanaged<CFWriteStream>?
        
        CFStreamCreatePairWithSocketToHost(nil, host as CFString, UInt32(port), &readStream, &writeStream)
        
        inputStream = readStream?.takeRetainedValue()
        inputStream?.delegate = self
        inputStream?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
        inputStream?.open()
    }
    
    // MARK: - NSStreamDelegate
    func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
        switch eventCode {
        case .OpenCompleted:
            print("✅ 服务器连接建立成功")
        case .HasBytesAvailable:
            readAvailableBytes()
        case .EndEncountered:
            print("🔌 服务器连接已断开")
            cleanUpStream()
        case .ErrorOccurred:
            if let error = inputStream?.streamError {
                print("❌ 连接出错: \(error.localizedDescription)")
            }
            cleanUpStream()
        default:
            break
        }
    }
    
    // MARK: - 数据读取与处理
    private func readAvailableBytes() {
        let bufferSize = 1024
        let buffer = UnsafeMutablePointer<UInt8>.alloc(bufferSize)
        
        while inputStream?.hasBytesAvailable == true {
            let bytesRead = inputStream?.read(buffer, maxLength: bufferSize) ?? 0
            
            if bytesRead > 0 {
                dataBuffer.appendBytes(buffer, length: bytesRead)
                processBufferedData()
            } else if bytesRead < 0 {
                print("❌ 读取数据出错")
                break
            }
        }
        
        buffer.dealloc(bufferSize)
    }
    
    private func processBufferedData() {
        var bytes = UnsafeMutablePointer<UInt8>(dataBuffer.mutableBytes)
        let totalBytes = dataBuffer.length
        var currentOffset = 0
        
        while currentOffset < totalBytes {
            // 查找分隔符0x00的位置
            guard let separatorIndex = findSeparator(at: bytes + currentOffset, length: totalBytes - currentOffset) else {
                // 未找到分隔符,剩余数据留待下次处理
                break
            }
            
            // 验证数据包格式:分隔符前至少有2个非零字节
            if separatorIndex >= 2 {
                let firstValue = bytes[currentOffset]
                let secondValue = bytes[currentOffset + 1]
                
                if firstValue != 0 && secondValue != 0 {
                    // 这里替换成你的业务逻辑,比如回调通知上层
                    print("📥 收到有效数据: 第一个值=\(firstValue), 第二个值=\(secondValue)")
                } else {
                    print("⚠️ 收到无效数据:存在零值字节,忽略该数据包")
                }
            } else {
                print("⚠️ 收到不完整数据包:分隔符前字节不足,继续等待")
            }
            
            // 移动偏移量到分隔符之后
            currentOffset += separatorIndex + 1
        }
        
        // 移除已处理的数据,保留未处理的部分
        if currentOffset > 0 {
            dataBuffer.replaceBytesInRange(NSMakeRange(0, currentOffset), withBytes: nil, length: 0)
        }
    }
    
    private func findSeparator(at bytes: UnsafePointer<UInt8>, length: Int) -> Int? {
        for i in 0..<length {
            if bytes[i] == 0x00 {
                return i
            }
        }
        return nil
    }
    
    // MARK: - 资源清理
    private func cleanUpStream() {
        inputStream?.close()
        inputStream?.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
        inputStream = nil
    }
}

使用示例

// 初始化读取器并连接服务器
let dataReader = BinaryDataReader()
dataReader.connectToServer("你的服务器IP/域名", port: 你的端口号)

// 注意:如果是命令行工具,需要手动启动RunLoop保持程序运行
// iOS或Mac应用中无需此行,因为已有主RunLoop
NSRunLoop.currentRunLoop().run()

关键细节说明

  • 异步读取:基于NSStream的委托模式实现异步数据读取,不会阻塞主线程
  • 数据缓存:用NSMutableData缓存未处理的字节,避免分批次读取导致的数据截断
  • 格式验证:额外检查两个值是否非零,确保只处理符合你要求的有效数据
  • 错误处理:包含连接断开、读取错误等场景的处理逻辑,保证稳定性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:59:59