我想与pool.ntp.org连接以进行时间同步。所以我正在创建一个套接字
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次正常工作。服务器发送响应,我的过程继续。问题是我在等待数据实际继续我的app逻辑。如果没有数据来kCFSocketDataCallBack
未被触发且应用等待永远。有没有办法让我等待接收数据超时?(没有自己NSTimer
重新连接到池)
答案 0 :(得分:1)
我认为重要的是要知道UDP本质上是不可靠的。
因此,数据包丢失并且您有时无法获得响应是绝对可能和正常的行为。你提到它有效的10次中的9次,对于基于UDP的协议听起来相当不错。
所以我认为你真的需要让你的代码变得更聪明一些。我也认为没有办法使用计时器来确定你是否真的在一定时间内收到了响应。
幸运的是,在循环中安排CFRunLoopTimer
非常容易。你需要做的是:
CFSocketSendData
时,您还会添加CFRunLoopTimer
。kCFSocketDataCallBack
回叫时,取消定时器CFRunLoopTimerSetNextFireDate
每次发送数据包时,都可以保留一个计数器。然后你可以在经过一定的尝试后放弃。
这是一个更多的代码,但它将使您的基于UDP的应用程序更加可靠。