2012-11-23 26 views
8

Chcę połączyć się z pool.ntp.org do synchronizacji czasu. Więc tworzę gniazdoCzas oczekiwania na odebranie danych przez IOS CFsocket

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

następnie am utworzenie pętli

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

i podłączenie do adresu

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

jeśli mam callback kCFSocketWriteCallBack i przesłać wymagane dane

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

wszystko, aż tutaj działa idealnie. Mój prawdziwy problem jest pod

else if(callbackType==kCFSocketDataCallBack) 

9/10 razy działa dobrze. serwer wysyła odpowiedź i mój proces jest kontynuowany. Problem polega na tym, że czekam na rzeczywiste dane, aby kontynuować moją logikę aplikacji. jeśli nie ma danych, kCFSocketDataCallBack nie jest wywoływane, a aplikacja czeka na zawsze. Czy jest jakiś sposób, aby ustawić limit czasu na oczekiwanie na otrzymanie danych? (Bez posiadania przez siebie NSTimer, aby ponownie połączyć się z pulą)

+0

Mam ten sam problem, czy znalazłeś jakieś rozwiązanie? – xjdrew

Odpowiedz

1

Myślę, że ważne jest, aby wiedzieć, że UDP jest z natury niewiarygodne.

Jest zatem absolutnie możliwe i normalne zachowanie, że pakiety gubią się i czasami nie otrzymujesz odpowiedzi. Wspomniałeś 9 na 10 razy, co działa, co brzmi całkiem nieźle dla protokołu opartego na protokole UDP.

Uważam, że naprawdę trzeba sprawić, by kod był trochę mądrzejszy. Sądzę też, że nie ma sposobu, aby użyć timera, aby dowiedzieć się, czy rzeczywiście otrzymałeś odpowiedź w ciągu określonej ilości czasu.

Na szczęście bardzo łatwo jest zaplanować CFRunLoopTimer w swojej pętli. Co trzeba zrobić, to:

  1. Po wywołaniu CFSocketSendData po raz pierwszy można również dodać CFRunLoopTimer.
  2. Po otrzymaniu oddzwonienia anulowanie timera
  3. Jeśli nigdy nie otrzymasz odpowiedzi lub jeśli odpowiedź nadejdzie naprawdę późno, twój timer się uruchomi. Więc może po prostu wysłać pakiet ponownie od czasu timera zwrotnego i zaplanować go ponownie CFRunLoopTimerSetNextFireDate

Możesz zachować licznik wokół, że przyrost wartości za każdym razem wysłać paczkę. Następnie możesz porzucić określoną liczbę prób.

To trochę więcej kodu, ale sprawi, że Twoja aplikacja oparta na protokole UDP stanie się bardziej niezawodna.