0

In an iOS app I am making an audio file transfer using CoreBlueTooth L2CAP channel, between one device and another one. It is already half working but not yet entirely. At this point I have transferred the file name, but coming to the file contents, here is the situation.

On the sending side all the bytes are sent (a few hundred thousands bytes) spread over several chunks. But on the receiving side, only the first few thousands bytes seem to reach destination.

The function:

func stream(_ aStream: Stream,
            handle eventCode: Stream.Event) {
    ......
}

is called once (with Stream.Event.hasBytesAvailable) and gets the first few thousands bytes. But then it is never called again. What could be the reason for that? I expect it to be called as many times as necessary until all the bytes have been received.

Michel
  • 10,303
  • 17
  • 82
  • 179
  • Please show your sending code. After you receive some bytes you should check `hasBytesAvailable` on the stream and call `read` again if there are still bytes available. You can't rely on the event handler being called. Check my updated peripheral code in the largedata branch – Paulw11 Sep 03 '19 at 08:52

1 Answers1

0

After you complete the read you need to check the stream's hasBytesAvailable property and issue another read if it is true. The event handler may not be called.

For example:

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
    switch eventCode {
    case Stream.Event.openCompleted:
        print("Stream is open")
    case Stream.Event.endEncountered:
        print("End Encountered")
    case Stream.Event.hasBytesAvailable:
        print("Bytes are available")
        self.readBytes(from: aStream as! InputStream)
    case Stream.Event.hasSpaceAvailable:
        print("Space is available")
    case Stream.Event.errorOccurred:
        print("Stream error")
    default:
        print("Unknown stream event")
    }
}

func readBytes(from stream: InputStream) {
    let bufLength = 1024
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufLength)
    let bytesRead = stream.read(buffer, maxLength: bufLength)
    print("bytesRead = \(bytesRead)")
    self.bytesReceived += bytesRead
    if stream.hasBytesAvailable {
        self.readBytes(from: stream)
    }
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • OK. I was not aware of having to run this: if stream.hasBytesAvailable { self.readBytes(from: stream) } I thought the stream function was automatically called and did it all. I will try that. – Michel Sep 03 '19 at 09:39
  • Is that documented somewhere from Apple? – DrMickeyLauer Dec 11 '22 at 11:58
  • It is the standard way of dealing with a stream. The `hasBytesAvailable` event is only posted when the stream changes from no bytes available to has bytes available. The issue is that you don't know how many bytes are available and the most bytes you can read at once is the size of the buffer you pass. After the read you check to see if there are still bytes (the number of bytes available was more than your buffer size) and if there are, perform another read as you won't get a hasBytesAvailable event – Paulw11 Dec 11 '22 at 18:37