2016-07-23 1 views
-1

garder le calme, très probablement cette question n'est pas un doublon. J'ai déjà essayé toutes les solutions en débordement de pile, mais rien n'a fonctionné pour moi. J'ai un thread client qui envoie et reçoit une chaîne "keepalive" (un ping) en continu à partir d'un autre hôte. S'il ne reçoit pas le "keepalive" dans le KeepAliveMax, il ferme les flux et dit au revoir (en théorie, mais cela fonctionne encore en cours). Maintenant, mon problème est que j'ai utilisé un NSTimer pour appeler la fonction updateKeepAlive, mais jamais invoked..I ne comprennent pas pourquoi :( j'ai aussi essayé de régler manuellement la NSTimer runloop, mais il ne travaille pasNSTimer ne jamais appeler la fonction de sélection (Swift)

le suivi est la partie du code où la fonction de sélection doit être initialisé et a appelé toutes les secondes:

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

} 

et la suite est la fonction updateKeepAlive:

func updateKeepAlive(){ 

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

    /* in progress ..... 

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

Répondre

0

Dans un nouveau début de fil, il est pas d'inp Les sources ou les minuteurs sont attachés à la boucle d'exécution. Ainsi, la boucle d'exécution n'est pas active. Vous pouvez appeler la fonction run après l'appel scheduledTimerWithTimeInterval.

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