2016-07-23 3 views
-1

Ruhe bewahren, höchstwahrscheinlich ist diese Frage kein Duplikat. Ich habe schon alle Lösungen im Stacküberlauf ausprobiert, aber nichts hat für mich funktioniert. Ich habe einen Client-Thread, der eine Keepalive-Zeichenfolge (ein Ping) kontinuierlich von einem anderen Host sendet und empfängt. Wenn es nicht das "Keepalive" innerhalb des KeepAliveMax erhält, schließt es die Streams und sagt Auf Wiedersehen (in der Theorie, aber das ist noch in Arbeit). Nun mein Problem ist, dass ich eine NSTimer verwendet, um die updateKeepAlive Funktion zu nennen, aber es ist nie invoked..I verstehe nicht, warum :( ich versucht habe, auch manuell den NSTimer Runloop zu setzen, aber es funktioniert nichtNSTimer nie die Wählerfunktion aufrufen (Swift)

der Nachfolger ist der Teil des Codes, wo die Auswahlfunktion initialisiert und jede Sekunde aufgerufen werden soll:

public class Client: NSObject, NSStreamDelegate { 

var serverAddress: CFString 
let serverPort: UInt32 = 50000 

private var inputStream: NSInputStream! 
private var outputStream: NSOutputStream! 
private var connecting:Bool 
private var byteRead:Int 
private var byteWrite:Int 
private let keepAliveMax:Double = 5000 
private var keepAliveTime:Double 
private var connected:Bool 
var timer: NSTimer? 

init(ip:String) { 
    serverAddress = ip 
    connecting = false 
    connected = false 
    byteRead = 0 
    byteWrite = 0 
    keepAliveTime = 0 

    super.init() 

    let thread = NSThread(target:self, selector:#selector(connect), object:nil) 

    thread.start() 

    print("thread is started and now I can continue with other tasks..") 

} 

func connect() { 

    connecting = true 

    while connecting { 
     print("connecting...") 

     var readStream: Unmanaged<CFReadStream>? 
     var writeStream: Unmanaged<CFWriteStream>? 

     CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream) 

     // Documentation suggests readStream and writeStream can be assumed to 
     // be non-nil. If you believe otherwise, you can test if either is nil 
     // and implement whatever error-handling you wish. 

     self.inputStream = readStream!.takeRetainedValue() 
     self.outputStream = writeStream!.takeRetainedValue() 

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

     self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
     self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 

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

     // send handshake 

     byteWrite = writeLine("handshake") 
     print("written: \(byteWrite) for handshake") 


     // wait to receive handshake 
     print("waintig for handshake...") 


     if readLine() == "handshake" { 
      connected = true 

      print("Client: connection estabilished correctly") 

      // close the waiting popup and start with SendBox... 
      // in progress... 

      // send keepAlive 
      byteWrite = writeLine("keepalive") 
      print("written: \(byteWrite) for keepalive") 


      //======================== THIS NOT WORK PROPERLY ============================================================ 

      timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(Client.updateKeepAlive), userInfo: nil, repeats: true) 

      /* 
      timer = NSTimer(timeInterval: 1, target: self, selector: #selector(Client.updateKeepAlive), userInfo: nil, repeats: true) 

      NSRunLoop.currentRunLoop().addTimer(timer!, forMode: NSRunLoopCommonModes) 
      */ 

      //============================================================================================================ 

      keepAliveTime = NSDate().timeIntervalSince1970 * 1000 

      print("Client: Timer started") 

      while self.inputStream.streamStatus != NSStreamStatus.Closed || 
       self.outputStream.streamStatus != NSStreamStatus.Closed 
      { 
       print("Client: under the while of keepAlive"); 

       if readLine() == "keepalive" 
       { 
        keepAliveTime = NSDate().timeIntervalSince1970 * 1000 
        writeLine("keepalive") 

        print("Client: keepalive received"); 
       } 
       else 
       { 
        print("Client: not keepalive: "); 
        // close streams...... work in progress 
        break 

       } 

       sleep(1) 
      } 

     } 
     else{ 
      print("wrong handshake") 
     } 


     print("closing streams..") 
     connecting = false 

     self.inputStream.close() 
     self.outputStream.close() 
     self.timer?.invalidate() 
    } 

} 

und der Nachfolger ist die updateKeepAlive Funktion:

func updateKeepAlive(){ 

    print("in updateKeepalive function") // <---- NEVER PRINTED 

    /* in progress ..... 

    ........./* 
} 

Antwort

0

In einem neuen Thread Anfang gibt es keine Eingabe ut Quellen oder Timer sind an die Laufschleife angehängt. So ist die Laufschleife zwar nicht aktiv. Sie können die Funktion run nach dem Aufruf von terminatedTimerWithTimeInterval aufrufen.

timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(TimerTest.updateKeepAlive), userInfo: nil, repeats: true) 
NSRunLoop.currentRunLoop().run()