2012-11-23 3 views
8

pool.ntp.org와 연결하여 시간 동기화를 원합니다. 그래서IOS가 데이터 시간 초과를 수신함 CFsocket

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

다음 소켓을 만드는 오전하는 루프

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

을 설정하고 주소

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

에 연결 내가 kCFSocketWriteCallBack 콜백이 있다면 내가 필요한 데이터를 전송하고

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

여기까지 완벽하게 작동합니다. 내 실제 문제는로입니다

else if(callbackType==kCFSocketDataCallBack) 

9/10 번 작업이 정상입니다. 서버가 응답을 보내고 프로세스가 계속됩니다. 문제는 데이터가 실제로 내 앱 로직을 계속 수행 할 때까지 기다리는 것입니다. 데이터가 없으면 kCFSocketDataCallBack가 실행되지 않고 앱이 계속 대기합니다. 데이터를 받기 위해 시간 초과를 할 수있는 방법이 있습니까? (자신이 풀을 사용하지 않고 NSTimer을 사용하지 않고)

+0

동일한 문제가 발생합니다. 해결책을 찾았습니까? – xjdrew

답변

1

여기서 중요한 점은 UDP가 본질적으로 신뢰할 수 없다는 것입니다.

따라서 패킷이 손실되어 사용자가 응답을받지 못하는 것이 절대적으로 가능하고 정상적인 동작입니다. 10 번 중 9 번 작동한다고 말하면 UDP 기반 프로토콜 에선 꽤 좋은 소리입니다.

그래서 코드를 좀 더 똑똑하게 만들 필요가 있다고 생각합니다. 나는 또한 특정 양의 시간 내에 실제로 응답을 받았는지 알아 내기 위해 타이머를 사용하는 방법이 없다고 생각한다.

다행히도 루프에 CFRunLoopTimer을 예약하는 것은 매우 쉽습니다. 처음 CFSocketSendData를 호출 할 때

  1. 당신은 또한 CFRunLoopTimer를 추가 : 당신이해야 할 것은 이것이다.
  2. 콜백을 받으면 타이머를 취소합니다.
  3. 응답을받지 못하거나 응답이 정말로 늦게 오면 타이머가 작동합니다. 따라서 다시 시간 타이머 콜백에서 패킷을 보내고 다시 예약 할 수 있습니다. CFRunLoopTimerSetNextFireDate

패킷을 보낼 때마다 증가하는 카운터를 유지할 수 있습니다. 그러면 일정한 양의 시도 후에 포기할 수 있습니다.

이것은 조금 더 코드이지만 UDP 기반 앱을 훨씬 더 신뢰할 수있게합니다.

관련 문제