How to test if my remote socket NSStream are correctly open
First of all, you have to schedule the stream on a runloop:
inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
And, in your code, it's too soon to check the error. Because open()
is async operation, you have to wait the result using delegate
. Here is working example:
import Foundation
class Connection: NSObject, NSStreamDelegate {
var host:String?
var port:Int?
var inputStream: NSInputStream?
var outputStream: NSOutputStream?
func connect(host: String, port: Int) {
self.host = host
self.port = port
NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inputStream, outputStream: &outputStream)
if inputStream != nil && outputStream != nil {
// Set delegate
inputStream!.delegate = self
outputStream!.delegate = self
// Schedule
inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
print("Start open()")
// Open!
inputStream!.open()
outputStream!.open()
}
}
func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
if aStream === inputStream {
switch eventCode {
case NSStreamEvent.ErrorOccurred:
print("input: ErrorOccurred: \(aStream.streamError?.description)")
case NSStreamEvent.OpenCompleted:
print("input: OpenCompleted")
case NSStreamEvent.HasBytesAvailable:
print("input: HasBytesAvailable")
// Here you can `read()` from `inputStream`
default:
break
}
}
else if aStream === outputStream {
switch eventCode {
case NSStreamEvent.ErrorOccurred:
print("output: ErrorOccurred: \(aStream.streamError?.description)")
case NSStreamEvent.OpenCompleted:
print("output: OpenCompleted")
case NSStreamEvent.HasSpaceAvailable:
print("output: HasSpaceAvailable")
// Here you can write() to `outputStream`
default:
break
}
}
}
}
Then:
let conn = Connection()
conn.connect("www.example.com", port: 80)
Admin
Updated on June 13, 2022Comments
-
Admin almost 2 years
TL;DR : What's the way to check if my remote stream are opened correctly after a call to
NSStream.getStreamsToHostWithName(...)
?My application is a mobile IOS8 swift application.
I am using NSStream for input and output socket communication with a remote server.
To connect to my server and open my stream I use this code:
func connect(host: String, port: Int) -> Bool { //clear the previous connection if existing (and update self.connected) disconnect() //updating the current connection self.host = host self.port = port //pairing NSstreams with remote connection NSStream.getStreamsToHostWithName(self.host!, port: self.port!, inputStream: &inputStream, outputStream: &outputStream) if (self.inputStream != nil && self.outputStream != nil) { //open streams self.inputStream?.open() self.outputStream?.open() } if self.outputStream?.streamError == nil && self.inputStream?.streamError == nil { println("SOK") //PROBLEM 1 } //error checking after opening streams // PROBLEM 2 if var inputStreamErr: CFError = CFReadStreamCopyError(self.inputStream)? { println("InputStream error : " + CFErrorCopyDescription(inputStreamErr)) } else if var outputStreamErr: CFError = CFWriteStreamCopyError(self.outputStream)? { println("OutStream error : " + CFErrorCopyDescription(outputStreamErr)) } else { //set the delegate to self self.inputStream?.delegate = self self.outputStream?.delegate = self self.connected = true } //return connection state return self.connected }
My problem is located at //PROBLEM1 and //PROBLEM2.
At these points I try to determine if my sockets are opened correctly, but even if the server is not running this code still works, then the read and write operations are failing. I would like to be able to determine if the connection failed or not.
Maybe I am doing it totally wrong, I don't get how to test this.
-
Admin about 9 yearsThanks for this precise answer. I just have some questions. First, does doing the schedule part make my streams async? I want my operations to be synchronous.
-
rintaro about 9 yearsWith my understanding, stream itself is always non-blocking. If you need synchronous operation, you have to use polling with
while true { ... }
loop. see: developer.apple.com/library/ios/documentation/Cocoa/Conceptual/… -
Admin about 9 yearsI think stream is blocking, the NSInputStream.read() operation is blocking by default
-
Admin about 9 yearsAnyway, I used your answer to reshape my whole class. I am starting swift and it made me grasp delegates, events handling and runloop in swift. Thanks a lot!
-
Miracle Johnson about 9 yearsWhere i have to write this two lines ? inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode) outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
-
tp2376 over 5 yearsI am having same problem here : stackoverflow.com/questions/51938300/… . I added handle Event method after this but it's not triggering Any help Please..