17

失礼します。iPhone/Objective-Cの初心者ステータスをお願いします。

NSNetServiceBrowserを使用してHTTPサーバーを見つけましたが、サービスのIPアドレスとポートを見つけたいだけです。

デリゲートメソッドには次のようなものがあります。

NSNetService* server = [serverBrowser.servers objectAtIndex:0];

NSString            *name = nil;
NSData              *address = nil;
struct sockaddr_in  *socketAddress = nil;
NSString            *ipString = nil;
int                 port;
uint                 i;
for (i = 0; i < [[server addresses] count]; i++)
{
    name = [server name];
    address = [[server addresses] objectAtIndex:i];
    socketAddress = (struct sockaddr_in *)
    [address bytes];
    ipString = [NSString stringWithFormat: @"%s",
                inet_ntoa (socketAddress->sin_addr)];
    port = socketAddress->sin_port;
    NSLog(@"Server found is %s %d",ipString,port);
}

ただし、デリゲートが呼び出されても、forループは開始されません。何か案は?ありがとう!

4

3 に答える 3

44

これは古いスレッドだと思いますが、これにも出くわしました。上記のコードにはいくつかの問題があります。

  1. IPv6に精通していません。少なくとも、アプリの残りの部分がv4アドレスしか処理できない場合は、IPv6アドレスを検出して破棄する必要がありますが、理想的には、両方のアドレスファミリーをアップストリームに渡す準備をする必要があります。

  2. ポートの割り当てにより、Intelプロセッサに対して誤った値が生成されます。あなたはhtons それを修正するために使用する必要があります。

  3. Andrewが上記で述べたように、反復では拡張forループを使用する必要があります。

  4. (編集:これを追加)別の関連スレッドで述べたように、の使用inet_ntoaは推奨されていませんinet_ntop

これらすべてをまとめると、次のようになります。

char addressBuffer[INET6_ADDRSTRLEN];

for (NSData *data in self.addresses)
{
    memset(addressBuffer, 0, INET6_ADDRSTRLEN);

    typedef union {
        struct sockaddr sa;
        struct sockaddr_in ipv4;
        struct sockaddr_in6 ipv6;
    } ip_socket_address;

    ip_socket_address *socketAddress = (ip_socket_address *)[data bytes];

    if (socketAddress && (socketAddress->sa.sa_family == AF_INET || socketAddress->sa.sa_family == AF_INET6))
    {
        const char *addressStr = inet_ntop(
                socketAddress->sa.sa_family,
                (socketAddress->sa.sa_family == AF_INET ? (void *)&(socketAddress->ipv4.sin_addr) : (void *)&(socketAddress->ipv6.sin6_addr)),
                addressBuffer,
                sizeof(addressBuffer));

        int port = ntohs(socketAddress->sa.sa_family == AF_INET ? socketAddress->ipv4.sin_port : socketAddress->ipv6.sin6_port);

        if (addressStr && port)
        {
            NSLog(@"Found service at %s:%d", addressStr, port);
        }
    }
}
于 2011-02-12T07:01:26.457 に答える
18

コールバックで返される NSNetService は、使用する準備ができていません。アドレスを取得するには、次のメソッドを呼び出す必要があります。

- (void)resolveWithTimeout:(NSTimeInterval)timeout;

NSNetService デリゲート メソッドを実装して、いつ解決されるかを確認します。

- (void)netServiceDidResolveAddress:(NSNetService *)sender;

その時点で、サービスには少なくとも 1 つのアドレスが存在するはずです。

また、ドキュメントとヘッダー ファイルを注意深く読んでください。この問題には複雑な部分がありますが、これについては触れませんでした。

于 2009-06-02T08:48:23.093 に答える