2012-11-23 9 views
8

Ich möchte eine Verbindung mit pool.ntp.org herstellen, um die Zeit zu synchronisieren. So erschaffe eine BuchseIOS empfängt Daten-Timeout CFsocket

sock=CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP, kCFSocketDataCallBack|kCFSocketWriteCallBack|kCFSocketConnectCallBack, sockCallback, &sock_ctx); 

dann setze eine Schleife bis

sockref=CFSocketCreateRunLoopSource(NULL, sock, 0); 
CFRunLoopAddSource(CFRunLoopGetMain(), sockref, kCFRunLoopCommonModes); 

und an die Adresse Verbindungs ​​

CFDataRef adrref=CFDataCreate(NULL, (const UInt8 *)&adr, sizeof(adr)); 
    CFSocketError err=CFSocketConnectToAddress(sock, adrref,-1); 

wenn i Rückruf kCFSocketWriteCallBack habe ich senden die erforderlichen Daten

 CFDataRef bufref=CFDataCreate(NULL, buffer, scl->NTP_PACKET_SIZE); 
    CFSocketError error = CFSocketSendData(scl->sock, NULL, bufref,3); 

alles bis hier funktioniert einwandfrei. Mein aktuelles Problem ist bei

else if(callbackType==kCFSocketDataCallBack) 

9/10 mal funktioniert ok. Server sendet die Antwort und mein Prozess wird fortgesetzt. Das Problem ist, dass ich darauf warte, dass die Daten meine App-Logik fortsetzen. wenn keine Daten kommen kCFSocketDataCallBack wird nicht ausgelöst und App wartet auf immer. Gibt es eine Möglichkeit für mich, eine Zeitüberschreitung beim Warten auf den Empfang von Daten zu setzen (ohne NSTimer, um mich wieder mit dem Pool zu verbinden)

+0

Ich stoße auf das gleiche Problem, finden Sie irgendeine Lösung? – xjdrew

Antwort

1

Ich denke, das Wichtigste ist, dass UDP von Natur aus unzuverlässig ist.

Es ist daher absolut möglich und normales Verhalten, dass Pakete verloren gehen und dass Sie manchmal keine Antwort bekommen. Sie erwähnen 9 von 10 Mal, dass es funktioniert, das klingt ziemlich gut für ein UDP-basiertes Protokoll.

Also ich denke, Sie müssen wirklich Ihren Code ein wenig schlauer machen. Ich denke auch, dass es keinen Weg gibt, einen Timer zu verwenden, um herauszufinden, ob Sie tatsächlich eine Antwort innerhalb einer bestimmten Zeit erhalten haben.

Glücklicherweise ist es sehr einfach, einen CFRunLoopTimer auf Ihrem Loop zu planen. Was Sie tun müssen, ist dies:

  1. Wenn Sie CFSocketSendData zum ersten Mal rufen Sie auch CFRunLoopTimer hinzufügen.
  2. Wenn Sie einen kCFSocketDataCallBack Rückruf erhalten, brechen Sie den Timer ab
  3. Wenn Sie nie eine Antwort erhalten, oder wenn die Antwort wirklich spät kommt, wird Ihr Timer ausgelöst. So können Sie einfach das Paket wieder von Zeit Timer-Rückruf senden und planen wieder mit CFRunLoopTimerSetNextFireDate

können Sie einen Zähler halten um, dass Sie jedes Mal, wenn Sie ein Paket senden erhöhen. Dann kannst du nach einer bestimmten Anzahl von Versuchen aufgeben.

Dies ist ein wenig mehr Code, aber es wird Ihre UDP-basierte App viel zuverlässiger machen.