仅提供示例,因为每个项目对应的socket消息通讯协议几乎都是不同的,我这里每条消息的消息头占3个字节,其中第2、3字节是消息体长度(不包含消息头,大端模式)
import CocoaAsyncSocket
import UIKit
protocol WSSocketDataDelegate: AnyObject {
func didReceiveData(data: Data, ip: String?)
}
extension WSSocketDataDelegate {
func didReceiveData(data: Data, ip: String?) {}
}
private class WSClientDataProt {
var ip = ""
var block: ((Data) -> Void)?
private let queue = OperationQueue()
private var tcpCacheData = Data()
init() {
//串行
queue.maxConcurrentOperationCount = 1
}
func unpackMsg(data: Data) {
queue.addOperation { [weak self] in
guard let strongSelf = self else { return }
strongSelf.tcpCacheData.append(data)
while !strongSelf.tcpCacheData.isEmpty {
var lc: UInt16 = 0
guard strongSelf.tcpCacheData.count >= 3 else { break }
(strongSelf.tcpCacheData as NSData).getBytes(&lc, range: NSMakeRange(1, 2))
let len = Int(UInt16(bigEndian: lc)) + 3
guard let body = strongSelf.tcpCacheData.getSubData(start: 0, count: len) else { break }
strongSelf.block?(body)
strongSelf.removeCacheData(start: 0, num: len)
}
}
}
private func removeCacheData(start: Int, num: Int) {
guard start >= 0 && num >= 0 else { return }
guard tcpCacheData.count >= start + num else { return }
let startIndex = tcpCacheData.index(tcpCacheData.startIndex, offsetBy: start)
let endIndex = tcpCacheData.index(tcpCacheData.startIndex, offsetBy: start + num)
let range = startIndex ..< endIndex
tcpCacheData.removeSubrange(range)
}
}
class WSSocketDataManager: NSObject {
weak var delegate: WSSocketDataDelegate?
private static var manager: WSSocketDataManager?
public static var shared: WSSocketDataManager {
if manager == nil {
manager = WSSocketDataManager()
}
return manager!
}
func destroy() {
WSSocketDataManager.manager = nil
}
override private init() {}
private var clientDataDic = [String: WSClientDataProt]()
func didReceiveData(data: Data, TCPSock: GCDAsyncSocket? = nil, address: String?) {
// tcp
if let sock = TCPSock {
guard let add = sock.connectedHost else { return }
if let client = clientDataDic[add] {
client.unpackMsg(data: data)
} else {
let clientData = WSClientDataProt()
clientData.ip = add
clientDataDic[add] = clientData
clientData.block = { [weak self] packet in
self?.delegate?.didReceiveData(data: packet, ip: add)
}
clientData.unpackMsg(data: data)
}
}
// udp
else {
delegate?.didReceiveData(data: data, ip: address)
}
}
// socket断开时调用
func removeSocketData(sock: GCDAsyncSocket) {
guard let add = sock.connectedHost else { return }
clientDataDic.removeValue(forKey: add)
}
}