I'm trying to make a client application in Swift and I've chosen to follow this tutorial as an inspiration: https://www.raywenderlich.com/157128/real-time-communication-streams-tutorial-ios
I send binary data to the output stream and my server gets the request successfully and answers back. Unfortunately, the Swift client application's StreamDelegate is never triggered.
I've developed in the Playgrounds a simple example of a HTTP request similar to what my application is doing and the same problem occurs:
import UIKit
class WebServerConnection: NSObject, StreamDelegate {
let host: String
var inputStream: InputStream!
var outputStream: OutputStream!
var responseHandler:((String) -> Void)?
init(_ host:String) {
self.host = host
}
func setup(responseHandler:((String) -> Void)?) {
self.responseHandler = responseHandler
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host as CFString, 80, &readStream, &writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream.delegate = self
inputStream.schedule(in: .current, forMode: .commonModes)
outputStream.schedule(in: .current, forMode: .commonModes)
inputStream.open()
outputStream.open()
}
func query(_ path:String = "/") {
let data = "GET \(path) HTTP/1.1\r\nhost: \(host)\r\n\r\n".data(using: .utf8)!
_ = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) }
print("sent!")
}
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch eventCode {
case Stream.Event.hasBytesAvailable:
printAvailableBytes(stream: aStream as! InputStream)
case Stream.Event.endEncountered:
print("<End Encountered>")
case Stream.Event.errorOccurred:
print("<Error occurred>")
default:
print("<Some other event>")
}
}
func printAvailableBytes(stream: InputStream) {
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 4096)
while stream.hasBytesAvailable {
let numberOfBytesRead = inputStream.read(buffer, maxLength: 4096)
if numberOfBytesRead < 0 {
if stream.streamError != nil {
break
}
}
if let message = String(bytesNoCopy: buffer, length: numberOfBytesRead, encoding: .utf8, freeWhenDone: true) {
responseHandler?(message)
}
}
}
func close() {
inputStream.close()
outputStream.close()
}
}
let google = WebServerConnection("google.com")
google.setup() { message in
print(message)
google.close()
}
google.query()
I get the "sent!" message in the console, but nothing else! I thought with the input.delegate = self
, the stream function would be called with the response. What am I missing?