Sockets 如何测试远程套接字NSStream是否正确打开

Sockets 如何测试远程套接字NSStream是否正确打开,sockets,swift,ios8,nsstream,Sockets,Swift,Ios8,Nsstream,TL;DR:调用NSStream.getStreamsToHostWithName(…)后,如何检查远程流是否正确打开 我的应用程序是一个移动IOS8 swift应用程序 我使用NSStream与远程服务器进行输入和输出套接字通信 要连接到我的服务器并打开我的流,我使用以下代码: func connect(host: String, port: Int) -> Bool { //clear the previous connection if existing (and updat

TL;DR:调用
NSStream.getStreamsToHostWithName(…)
后,如何检查远程流是否正确打开

我的应用程序是一个移动IOS8 swift应用程序

我使用NSStream与远程服务器进行输入和输出套接字通信

要连接到我的服务器并打开我的流,我使用以下代码:

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
}
我的问题位于//问题1和//问题2

在这些点上,我试图确定套接字是否正确打开,但即使服务器没有运行此代码,代码仍然可以工作,那么读写操作也会失败。 我希望能够确定连接是否失败

也许我做得完全不对,我不知道如何测试它。

首先,你必须:

而且,在您的代码中,检查错误还为时过早。由于
open()
是异步操作,因此必须使用
委托等待结果。下面是一个工作示例:

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
        }
    }
}

}
然后:


谢谢你的准确回答。我只是有些问题。首先,执行调度部分是否使我的流异步?我希望我的操作是同步的。据我所知,流本身总是非阻塞的。如果需要同步操作,则必须在true{…}
循环时使用轮询。请看:我认为流是阻塞的,NSInputStream.read()操作是被默认值阻塞的。不管怎样,我用你的答案重塑了我的整个类。我正在启动swift,它让我掌握了swift中的代理、事件处理和runloop。谢谢!我要在哪里写这两行?输入流!。scheduleInRunLoop(.mainRunLoop(),forMode:NSDefaultRunLoopMode)outputStream!。scheduleInRunLoop(.mainRunLoop(),forMode:NSDefaultRunLoopMode)
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
        }
    }
}

}
let conn = Connection()
conn.connect("www.example.com", port: 80)