swift 实现Socket连接附data转义例子
2023-07-26 本文已影响0人
UILable攻城狮
基于CocoaAsyncSocket 实现socket连接
- 创建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("连接成功")
}
- GCDAsyncSocketDelegate 连接成功 失败 收到数据等
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.pngimage.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
}