2

Apple の TCPServer クラスを使用して、着信接続からリッスンするときにソケットを開きます。誰かがリッスン ソケットに接続したときに呼び出されるコールバックを次に示します。

static void TCPServerAcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
TCPServer *server = (TCPServer *)info;
if (kCFSocketAcceptCallBack == type) { 
    // for an AcceptCallBack, the data parameter is a pointer to a CFSocketNativeHandle
    CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;
    uint8_t name[SOCK_MAXADDRLEN];
    socklen_t namelen = sizeof(name);
    NSData *peer = nil;
    if (0 == getpeername(nativeSocketHandle, (struct sockaddr *)name, &namelen)) {
        peer = [NSData dataWithBytes:name length:namelen];
    }

    CFReadStreamRef readStream = NULL;
    CFWriteStreamRef writeStream = NULL;
    CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);
    if (readStream && writeStream) {
        CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        [server handleNewConnectionFromAddress:peer inputStream:(NSInputStream *)readStream outputStream:(NSOutputStream *)writeStream];
    } else {
        // on any failure, need to destroy the CFSocketNativeHandle 
        // since we are not going to use it any more
        close(nativeSocketHandle);
    }
    if (readStream) CFRelease(readStream);
    if (writeStream) CFRelease(writeStream);
}
}

接続しているデバイスのホスト名を取得する方法はありますか? よろしく、コサ

[編集] IPを抽出するために次のようなことを試しました:

struct sockaddr_in *s = (struct sockaddr_in*)name;
char *ipstr = malloc(INET_ADDRSTRLEN);         
ipstr = inet_ntoa(s->sin_addr);

NSLog(@"ip = %s", ipstr);

しかし、それは私に0.0.0.0を与えます。

[編集] まだ取り組んでいますが、まだ成功していません。アップルのドキュメントによると、アドレスパラメータは次のとおりです。

s のプロトコル ファミリ (たとえば、struct sockaddr_in または struct sockaddr_in6) に適した struct sockaddr の内容を保持し、s が接続されているリモート アドレスを識別する CFData オブジェクト。この値は、kCFSocketAcceptCallBack および kCFSocketDataCallBack コールバックを除いて NULL です。

ただし、132.20.0.1 以外の IP を抽出することはできません (これは明らかに私が期待している IP ではありません)。

4

1 に答える 1

2

アドレスを取得するためにあなたの方法に従おうとした後、私のために働いているあなたのコードのわずかな変形を思いつきました。IPv6 アドレスを扱っている場合、このコードは機能しますが、IPv4 で機能するように変更するのは簡単です。とにかく両方で動作するようにコードを変更する必要があります。

- (void)getPublicClientAddress {
    // Get public IP from stream

    // Get hands on appropriate data structures via the socket number
    CFSocketNativeHandle nativeSocketHandle = _socketnumber;
    uint8_t name[SOCK_MAXADDRLEN];
    socklen_t namelen = sizeof(name);
    NSData *peer = nil;
    if (0 == getpeername(nativeSocketHandle, (struct sockaddr *)name, &namelen)) {
        peer = [NSData dataWithBytes:name length:namelen];
    }

    // TODO distiguish between ipv4 and ipv6
    struct sockaddr_in6 *s = (struct sockaddr_in6*)name;

    // convert ip to string
    char *ipstr = malloc(INET6_ADDRSTRLEN);
    struct in6_addr *ipv6addr = &s->sin6_addr;  // used pointer here, but that really should make no difference
    inet_ntop(AF_INET6, ipv6addr, ipstr, sizeof(ipstr)); // used a different function here

    // convert port to int
    int portnumber = s->sin6_port;

    // Save in properties
    _publicIP   = [NSString stringWithFormat:@"%s", ipstr];
    _publicPort = [NSString stringWithFormat:@"%d", portnumber];
}

したがって、このコードは私にとっては機能しており、答えを探しているときにこの投稿に出くわした人に役立つことを願っています.

于 2013-11-21T08:14:39.737 に答える