CFHostによる名前解決
TCPソケット通信の記事に関連して、 CFHostを使いまわせば名前解決が最初の一度で済むなとかアホなことを考えて、ちょっと実装してみることにしました。
手順は公式ドキュメントのネットワーキングコンセプトの通りで、
- CFHostCreateWithNameでCFHostRefオブジェクトを作成
- CFHostSetClientを実行
- CFHostScheduleWithRunLoopを呼び出す
- CFHostStartInfoResolutionで名前解決を開始
- コールバックでアドレスを取得
と、ちょっと面倒です。コードにすると↓のような感じ。
// CallBack関数
void func_cfhost_client_callback(CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info){
Boolean resolved;
CFArrayRef addr = CFHostGetAddressing(theHost, &resolved);
}
// 名前解決開始
- (BOOL)startResolution:(NSString*)hostname
{
CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault,(__bridge CFStringRef)hostname);
CFHostClientContext clientContext = {0,NULL,NULL,NULL,NULL};
CFHostSetClient(host, func_cfhost_client_callback, &clientContext);
CFHostScheduleWithRunLoop(host, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
CFStreamError err;
return CFHostStartInfoResolution(host, kCFHostAddresses, &err);
}
こうやって頑張って作ったCFHostを、CFStreamCreatePairWithSocketToCFHost に渡してソケット通信をすれば、名前解決が一度で済んでいいよねとか…冒頭のアホな考えにいたるわけですが、いろいろと動作テストをするうちに、どうやらDNSキャッシュはCFHostの中にあるわけじゃなさそうだというのに気づいた次第で…(androidというかJavaだとInetAddressの実体がもってますよね)
結論としては、メンドクサイCFHostなんて作らずに、CFStreamCreatePairWithSocketToHostを呼ぶだけで解決じゃないかということになります。
これを実装するのに結構いろいろと調べ回って勉強になったのでよしとしますが、時間的なロスは正直痛い…