如何通过 CBL2CAPChannel 发送和接收数据
How to send and receive data via CBL2CAPChannel
我正在尝试在 2 个 iOS 设备之间打开一个 L2CAP 通道并双向传输数据。其中一个设备充当中央设备,另一个设备充当外围设备。
外围端:
我像这样发布一个 L2CAPChannel:
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
peripheral.publishL2CAPChannel(withEncryption: false)
}
}
加密的真假都试过了。
然后,频道发布后,我从 didPublishL2CAPChannel 委托方法中获取 PSM,并创建一个具有包含 PSM 值的特征的服务,并开始宣传它。
中央一侧:
我扫描外围设备,找到合适的设备,连接到它,开始发现服务,一旦发现服务,我就会发现特征。我找到特征,读取它的值并获得 PSM。然后我这样做:
self.peripheral.openL2CAPChannel(psm)
然后我在通道打开的委托方法中得到回调并执行此操作:
func peripheral(_ peripheral: CBPeripheral, didOpen channel: CBL2CAPChannel?, error: Error?) {
guard error == nil else {
print("Couldn't open channel. Error: \(error!.localizedDescription)")
return
}
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.outputStream.delegate = self
print("L2CAP channel opened with \(peripheral.name ?? "unknown")")
}
这会打印:
L2CAP channel opened with mrsta’s iPad
再次在外围:
我在委托方法中得到回调:
func peripheralManager(_ peripheral: CBPeripheralManager, didOpen channel: CBL2CAPChannel?, error: Error?) {
guard error == nil else {
print("Couldn't open channel. Error: \(error!.localizedDescription)")
return
}
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.outputStream.delegate = self
print("L2CAP channel opened")
}
这会打印:
[CoreBluetooth] No central present! Creating a new object. This shouldn't happen.
L2CAP channel opened
到目前为止,通道似乎在两侧都打开了。我只是想知道上面打印的消息是什么“...没有中央礼物!...”
一段时间后,我开始在控制台中收到这样的消息:
[CoreBluetooth] WARNING: Unknown error: 436
[CoreBluetooth] No known channel matching peer <CBPeripheral: 0x2829de120, identifier = 241BAA6F-0BFD-9F5A-1EC9-35A4FD246DF5, name = mrsta’s iPad, state = connected> with psm 192
[CoreBluetooth] WARNING: Unknown error: 431
我不知道这些是什么意思。有什么建议吗?
我还在两边实现了 StreamDelegate 方法:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
print("Stream Event occurred: \(eventCode)")
if eventCode == .hasSpaceAvailable {
self.tryToWrite()
}
}
但是上面的委托方法从来没有被调用过。我尝试像这样写入输出流(从中央端的 didOpen 通道委托方法调用的 tryToWrite):
func tryToWrite() {
let string = "Hello"
let stringData = Data(from: string)
let _ = stringData.withUnsafeBytes { write(stuff: [=18=], to: self.l2capChannel, withMaxLength: stringData.count) }
}
func write(stuff: UnsafePointer<UInt8>, to channel: CBL2CAPChannel?, withMaxLength maxLength: Int) {
let result = channel?.outputStream.write(stuff, maxLength: maxLength)
print("Write result: \(String(describing: result))")
}
结果是:
Write result: Optional(-1)
根据文档说明写入失败。
请告诉我我错过了什么?打开频道后出现的错误是什么?写入和读取数据的正确方法是什么?
我使用 L2CAP 并且它正在工作。我在两个 "didOpen" 函数中所做的是
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.inputStream.schedule(in: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.inputStream.open()
self.l2capChannel?.outputStream.delegate = self
self.l2capChannel?.outputStream.schedule(in: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.outputStream.open()
当我不再需要它们时,我将它们关闭
self.l2capChannel?.inputStream.close()
self.l2capChannel?.inputStream.remove(from: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.outputStream.close()
self.l2capChannel?.outputStream.remove(from: .main, forMode: .defaultRunLoopMode)
self.l2capChannel? = nil
我正在尝试在 2 个 iOS 设备之间打开一个 L2CAP 通道并双向传输数据。其中一个设备充当中央设备,另一个设备充当外围设备。
外围端:
我像这样发布一个 L2CAPChannel:
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
peripheral.publishL2CAPChannel(withEncryption: false)
}
}
加密的真假都试过了。
然后,频道发布后,我从 didPublishL2CAPChannel 委托方法中获取 PSM,并创建一个具有包含 PSM 值的特征的服务,并开始宣传它。
中央一侧:
我扫描外围设备,找到合适的设备,连接到它,开始发现服务,一旦发现服务,我就会发现特征。我找到特征,读取它的值并获得 PSM。然后我这样做:
self.peripheral.openL2CAPChannel(psm)
然后我在通道打开的委托方法中得到回调并执行此操作:
func peripheral(_ peripheral: CBPeripheral, didOpen channel: CBL2CAPChannel?, error: Error?) {
guard error == nil else {
print("Couldn't open channel. Error: \(error!.localizedDescription)")
return
}
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.outputStream.delegate = self
print("L2CAP channel opened with \(peripheral.name ?? "unknown")")
}
这会打印:
L2CAP channel opened with mrsta’s iPad
再次在外围:
我在委托方法中得到回调:
func peripheralManager(_ peripheral: CBPeripheralManager, didOpen channel: CBL2CAPChannel?, error: Error?) {
guard error == nil else {
print("Couldn't open channel. Error: \(error!.localizedDescription)")
return
}
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.outputStream.delegate = self
print("L2CAP channel opened")
}
这会打印:
[CoreBluetooth] No central present! Creating a new object. This shouldn't happen.
L2CAP channel opened
到目前为止,通道似乎在两侧都打开了。我只是想知道上面打印的消息是什么“...没有中央礼物!...”
一段时间后,我开始在控制台中收到这样的消息:
[CoreBluetooth] WARNING: Unknown error: 436
[CoreBluetooth] No known channel matching peer <CBPeripheral: 0x2829de120, identifier = 241BAA6F-0BFD-9F5A-1EC9-35A4FD246DF5, name = mrsta’s iPad, state = connected> with psm 192
[CoreBluetooth] WARNING: Unknown error: 431
我不知道这些是什么意思。有什么建议吗?
我还在两边实现了 StreamDelegate 方法:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
print("Stream Event occurred: \(eventCode)")
if eventCode == .hasSpaceAvailable {
self.tryToWrite()
}
}
但是上面的委托方法从来没有被调用过。我尝试像这样写入输出流(从中央端的 didOpen 通道委托方法调用的 tryToWrite):
func tryToWrite() {
let string = "Hello"
let stringData = Data(from: string)
let _ = stringData.withUnsafeBytes { write(stuff: [=18=], to: self.l2capChannel, withMaxLength: stringData.count) }
}
func write(stuff: UnsafePointer<UInt8>, to channel: CBL2CAPChannel?, withMaxLength maxLength: Int) {
let result = channel?.outputStream.write(stuff, maxLength: maxLength)
print("Write result: \(String(describing: result))")
}
结果是:
Write result: Optional(-1)
根据文档说明写入失败。
请告诉我我错过了什么?打开频道后出现的错误是什么?写入和读取数据的正确方法是什么?
我使用 L2CAP 并且它正在工作。我在两个 "didOpen" 函数中所做的是
self.l2capChannel = channel
self.l2capChannel?.inputStream.delegate = self
self.l2capChannel?.inputStream.schedule(in: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.inputStream.open()
self.l2capChannel?.outputStream.delegate = self
self.l2capChannel?.outputStream.schedule(in: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.outputStream.open()
当我不再需要它们时,我将它们关闭
self.l2capChannel?.inputStream.close()
self.l2capChannel?.inputStream.remove(from: .main, forMode: .defaultRunLoopMode)
self.l2capChannel?.outputStream.close()
self.l2capChannel?.outputStream.remove(from: .main, forMode: .defaultRunLoopMode)
self.l2capChannel? = nil