miken.mkndev
miken.mkndev

Reputation: 1951

How to detect end of socket packet in Swift

I am building an HTTP server in Swift. The server will eventually run on Linux, but right now only compiles on Mac OS.

Anyways, I have the socket connections working perfectly and I'm able to receive the data stream, but I am having difficulty finding the best way to determine how to detect the end of the socket data stream.

I know there's many ways todo this, and I know that sockets basically just spit out pure binary data and have no concept of a "packet" that has a beginning and end. My question what are the best techniques used to detect the end of a packet sent from a web browser requesting a web page? I know for JSON it's pretty easy, but I'm curious about when the client is requesting a web page specifically.

Thanks

Upvotes: 0

Views: 861

Answers (1)

Bao HQ
Bao HQ

Reputation: 1184

InputStream did that for you, you don't have to care about that.

Try to use this:

import Foundation

typealias OnComing = (String) -> (Void)

class SocketClient: NSObject, StreamDelegate {

    var host:String?
    var port:Int?
    var inputStream: InputStream?
    var outputStream: OutputStream?

    var status = false;
    var output = ""
    var bufferSize = 1024;

    var onComing:OnComing!

    func makeCFStreamConnection(host: String, port: Int, onComing:@escaping OnComing) {

        self.host = host
        self.port = port
        self.onComing = onComing

        Stream.getStreamsToHost(withName: host, port: port, inputStream: &self.inputStream, outputStream: &self.outputStream)

        if self.inputStream != nil && self.outputStream != nil {

            self.inputStream!.delegate = self
            self.outputStream!.delegate = self

            self.inputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)
            self.outputStream!.schedule(in: .main, forMode: RunLoopMode.defaultRunLoopMode)

            self.inputStream!.open()
            self.outputStream!.open()

        }


    }

    func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
        if aStream === self.inputStream {
            switch eventCode {
            case Stream.Event.errorOccurred:
                break
            case Stream.Event.openCompleted:
                break
            case Stream.Event.hasBytesAvailable:
                break
                read()
            default:
                break
            }
        } else if aStream === self.outputStream {
            switch eventCode {
            case Stream.Event.errorOccurred:
                break
            case Stream.Event.openCompleted:
                break
            case Stream.Event.hasSpaceAvailable:
                break
            default:
                break
            }
        }
    }

    func read() {
        var buffer = [UInt8](repeating: 0, count: bufferSize)
        while (self.inputStream!.hasBytesAvailable) {
            let bytesRead: Int = inputStream!.read(&buffer, maxLength: buffer.count)
            if bytesRead >= 0 {
                output += NSString(bytes: UnsafePointer(buffer), length: bytesRead, encoding: String.Encoding.ascii.rawValue)! as String
            } else {
                print("# Stream read() error")
            }
        }
        self.onComing(output)
    }

    func write(message:String) {
        let encodedDataArray = [UInt8]("\(message)\n".utf8)
        self.outputStream?.write(encodedDataArray, maxLength: encodedDataArray.count)
    }
}

Your problem is resolved by read()

Upvotes: 1

Related Questions