如何在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
相关产品推荐
相关产品推荐

