URLSessionStreamTask - readData eof never true

Hi,


I'm trying to implement a line bases protocol via a TCP socket. SO far I can enable the connection, send and receive data.

But I struggle to detect the stream buffer is empty while reading so I can process the content read.


My test is based on an example I found form eskimo.

Here is, what I do for the moment:


    static let shared = StreamQuoteServer()
    private override init() {}

    private lazy var session: URLSession = {
        let config = URLSessionConfiguration.default
        return URLSession(configuration: config, delegate: self, delegateQueue:
            OperationQueue.main)
    }()
    
    private var stream: URLSessionStreamTask!
    
    // callback if something comes in from server side
    func startRead(stream: URLSessionStreamTask) {
        stream.readData(ofMinLength: 1, maxLength: 200, timeout: 60.0) { (data, eof, error) in
            if let error = error {
                NSLog("read error")
            }
            if let data = data {
                // finaly we got some real data from the server!
                let responseString = String(data: data, encoding: .utf8)!
                print("\(responseString)")
            }
            NSLog("read eof %@", eof ? "true" : "false")
            if error == nil && !eof {
                self.startRead(stream: stream)
            }
        }
    }
    
    func connectServer() {
        stream = self.session.streamTask(withHostName: "a remote server", port: 1234)
        stream.resume()
        // needed if we use TLS later on ?
        // stream.startSecureConnection()
        
        self.startRead(stream: stream)
    }
    
    func disconnectServer() {
        NSLog("stop")
        sendCommand("q\n")
        stream.closeRead()
        stream.closeWrite()
        self.stream = nil
    }
    
    func login() {
        sendCommand("login\n")
    }

    func getData() {
          sendCommand("s123@1\n")          // this will request data with output
    } 

    private func sendCommand(_ command: String) {
        let hello = command.data(using: .utf8)!
        stream.write(hello, timeout: 60.0) { (error) in
            if let error = error {
                NSLog("write error")
            } else {
                NSLog("write complete")
            }
        }
    }


In Line 23 eof will never reache true - the results are more that 200 bytes long and I can see them all completly get read.

After reading the last char the timeout will trigger an error.

I'm trying to implement a line bases protocol … But I struggle to detect the stream buffer is empty while reading so I can process the content read.

Ah, um, that’s not how you implement a line-based protocol. Rather, you must parse the incoming data looking for line breaks. This is necessary because TCP does not preserve record boundaries, so the lines sent by the sender can be arbitrarily broken up, and then delayed, before being seen by the receiver.

The TCPTransports sample code has a

LineUnframer
type that shows how to do this parsing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
URLSessionStreamTask - readData eof never true
 
 
Q