I tried to create a framer that splits a stream of ASCII bytes into frames separated by the pipe ascii character: "|".
So I made an NWProtocolFramerImplementation as seen in the attached document.
The problem is that from the moment I get a chunk that does not end with "|", the framer gets stuck on that chunk. So the other chunks that come after this incomplete chunk never fully arrive in the framer.parseInput(...) call. Because it always parses chunks of minimumIncompleteLength and hence never arrives to the point where the next "|" is.
Here is a simple reproduction of this problem:
Results in:
Notice that the fourth and fifth message are never received by the client. How should I write the Framer so that it receives messages after an incoming incomplete chunk?
So I made an NWProtocolFramerImplementation as seen in the attached document.
The problem is that from the moment I get a chunk that does not end with "|", the framer gets stuck on that chunk. So the other chunks that come after this incomplete chunk never fully arrive in the framer.parseInput(...) call. Because it always parses chunks of minimumIncompleteLength and hence never arrives to the point where the next "|" is.
Here is a simple reproduction of this problem:
Create a TCP server
Setup the server so that it sends chunks of messages when a client connects.
Connect to the server (created in 1.) using the framer from above.
Start receiving messages.
Code Block import Networklet client = DispatchQueue(label: "Server")let server = DispatchQueue(label: "Client")let networkParameters = NWParameters.tcpnetworkParameters.defaultProtocolStack.applicationProtocols.insert(NWProtocolFramer.Options(definition: PipeFramer.definition), at: 0)let server = try! NWListener(using: .tcp)server.newConnectionHandler = { connection in print("server: new connection from", connection.endpoint) print("server (client \(connection.endpoint)): state", connection.state) connection.viabilityUpdateHandler = { viable in print("server (client \(connection.endpoint)): state", connection.state) if viable { print("server: sending") connection.send(content: "A|Be||Sea".data(using: .utf8)!, isComplete: false, completion: .idempotent) serverQueue.asyncAfter(deadline: .now() + 5) { print("server: sending second part") connection.send(content: " is longer than expected|0|".data(using: .utf8)!, isComplete: true, completion: .idempotent) } serverQueue.asyncAfter(deadline: .now() + 8) { print("server: sending last part") connection.send(content: "Done|".data(using: .utf8)!, isComplete: true, completion: .idempotent) } } } connection.start(queue: serverQueue)}server.stateUpdateHandler = { state in print("server:", state) if state == .ready, let port = server.port { print("server: listening on", port) }}server.start(queue: serverQueue)let client = NWConnection(to: .hostPort(host: "localhost", port: server.port!), using: networkParameters)func receiveNext() { client.receiveMessage { (data, context, complete, error) in let content: String if let data = data { content = String(data: data, encoding: .utf8) ?? data.description } else { content = data?.debugDescription ?? "<no data>" } print("client: received \"\(content)\"", context.debugDescription, complete, error?.localizedDescription ?? "No error") receiveNext() }}client.stateUpdateHandler = { state in print("client:", state) if state == .ready { print("client: receiving") receiveNext() }}client.start(queue: clientQueue)
Results in:
Code Block server: waiting(POSIXErrorCode: Network is down)server: readyserver: listening on 54894client: preparingclient: readyclient: receivingserver: new connection from ::1.53179server (client ::1.53179): state setupserver (client ::1.53179): state readyserver: sendingclient: parsing buffer: "A|BeSea"client: minLength set to 1client: parsing buffer: "BeSea"client: minLength set to 1client: parsing buffer: "|Sea"client: minLength set to 1client: parsing buffer: "Sea"client: minLength set to 4client: parsing buffer: ""client: minLength set to 1client: received "A" Optional(Network.NWConnection.ContentContext) true No errorclient: received "Be" Optional(Network.NWConnection.ContentContext) true No errorclient: received "<no data>" Optional(Network.NWConnection.ContentContext) true No errorclient: parsing buffer: "Sea"client: minLength set to 4server: sending second partclient: parsing buffer: "Sea "client: minLength set to 5client: parsing buffer: "Sea i"client: minLength set to 6server: sending last partclient: parsing buffer: "Sea is"client: minLength set to 7client: parsing buffer: "Sea is "client: minLength set to 8
Notice that the fourth and fifth message are never received by the client. How should I write the Framer so that it receives messages after an incoming incomplete chunk?