swift 实现Socket连接附data转义例子

2023-07-26  本文已影响0人  UILable攻城狮

基于CocoaAsyncSocket 实现socket连接

// MARK: - 创建客户端Socket
    func setupClientSocket() {
        //在主队列中处理,  所有的回执都在主队列中执行。
        self.socket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main)
    }

func connectBtnClick(_ sender: Any) {
        if self.socket == nil {
            setupClientSocket()
        }
        do {
            if self.socket?.isConnected == false {
                try self.socket?.connect(toHost:  "192.168.43.1", onPort: 5789)
            }
        }
        catch {
            showLogMsg("连接失败...")
            return
        }
        showLogMsg("连接成功")
        
    }
 func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) {
        // 连接成功 需要发送心跳,否则无法收到消息
        let  heat = ["msgType": "HEARTBEAT", "value": “”]
        let  newdata = communicationShareByte.sendMessageToCar(heat)
//发送心跳数据
        self.socket?.write(newdata, withTimeout: -1, tag: 100)
//读取服务器数据
        self.socket?.readData(withTimeout: -1, tag: 100)
    }
    func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {
        showLogMsg("socket断开连接...")
    }
    func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) {        
        sock.readData(withTimeout: -1, tag: 100) //继续读取数据
// z这里可以获取服务器发送来的数据
// 根据不同的要求  有可能需要对数据转义 等 自己实现
// data就是你需要的数据啦
    }

附我自己的转义方法-

image.png
image.png
消息转义为避免消息出现粘包时,查找消息头出错而导致消息解析失败,需要对消息除了LinkHeader外的部分进行转义后再进行传输。

约定转义符为0x3D。
在本协议中需要对(byte)0x55、(byte)0xaa、0x3D这三个字符进行转义,转义方法为字符前加0x3D,然后与0x3D进行异或,0x3D本身也需要转义。如(byte)0x55转义为0x3D 0x68,0x3D转义为0x3D 0x00

 // 对数据进行转义
    static func escapeMessage(originalMessage: [UInt8]) -> [UInt8] {
        var escapedMessage: [UInt8] = []
        //0x3D = 61   0x55 = 85  0xAA = 170
        for byte in originalMessage {
            if byte == 0x3D || byte == 0x55 || byte == 0xAA {
                escapedMessage.append(0x3D)
                escapedMessage.append(byte ^ 0x3D)
            } else {
                escapedMessage.append(byte)
            }
        }
        
        return escapedMessage
    }
// 对数据进行反转义(还原为原始数据)
static  func unescapeMessage(escapedMessage: [UInt8]) -> [UInt8] {
    var originalMessage: [UInt8] = []
    
    var index = 0
    while index < escapedMessage.count {
        let byte = escapedMessage[index]
        if byte == 0x3D { //开头有0x3D 需要开始转义
            if index + 1 < escapedMessage.count {
                let nextByte = escapedMessage[index + 1]
                
                    let originalByte = nextByte ^ 0x3D
                    originalMessage.append(originalByte)
                    index += 2
                
            } else {
                originalMessage.append(byte)
                index += 1
            }
        } else {
            originalMessage.append(byte)
            index += 1
        }
    }
    
    return originalMessage
}
按照要求消息拼接 组装
 static func AssembleData(_ body: [UInt8]) -> [UInt8] {
        // 消息头,占用2个字节固定0x55、0xaa
        let byteHeader: [UInt8] = [0x55, 0xaa]
        
        // 数据类型,可定义传输的数据类型0x11为json,目前只有json可作为后期扩展
        let byteDataType: [UInt8] = [0x11]
        
        // 消息上下行,0x1(车机到app)、0x2(app到车机)
        let byteMsgType: [UInt8] = [0x2]
        
        // 消息长度,占用4个字节,只代表数据长度(字节)
        let byteLength = intToByteArray(body.count)
        
        // LinkHeader组成
        var message: [UInt8] = []
        message.append(contentsOf: byteHeader)
        message.append(contentsOf: byteDataType)
        message.append(contentsOf: byteMsgType)
        message.append(contentsOf: byteLength)
      
        // 拼接body
        message.append(contentsOf: body)
        
        return  message
 
    }

 static  func intToByteArray(_ i: Int) -> [UInt8] {
        var result = [UInt8](repeating: 0, count: 4)
        // 由高位到低位
        result[0] = UInt8((i >> 24) & 0xFF)
        result[1] = UInt8((i >> 16) & 0xFF)
        result[2] = UInt8((i >> 8) & 0xFF)
        result[3] = UInt8(i & 0xFF)
        
        return result
    }
上一篇下一篇

猜你喜欢

热点阅读