iossocketsnsstreamcfsocket

iOS Development: Get private IP and port from NSReadStream


I am developing an app for iOS. In my app there is a working TCP-connection to a server, realized via NSStreams. Now I need the port the connection is using which generates some problems.

I can get the IP from iterating through the interfaces of the device but for the portnumber I have to get the information from the socket. In the following code I try to get the socket from my working and open NSInputStream _readstream. The problem is, that CFSocketCopyAddress is nil and I cannot see why. Can somebody else?

Any help is very much appreciated!

// Initializing some variables we need
CFSocketContext context;
memset(&context, 0, sizeof(context));
context.info = (__bridge void*)self;
NSString *property = @"kCFStreamPropertySocketNativeHandle";

// Get hands on the used socket via the socket native handle
CFSocketNativeHandle *socketNativeHandle = (CFSocketNativeHandle*)CFReadStreamCopyProperty((__bridge CFReadStreamRef)(_readStream), (__bridge CFStringRef)(property));
CFSocketRef cfSocket = CFSocketCreateWithNative(NULL, *socketNativeHandle, kCFSocketNoCallBack, nil, &context);

// Ask the socket for the address information
CFDataRef               dataRef = CFSocketCopyAddress(cfSocket);                        // dataRef is always nil :(
struct sockaddr_in      *sockaddr = (struct sockaddr_in*)CFDataGetBytePtr(dataRef);

int portnumber = sockaddr->sin_port;

Solution

  • OKay, this works for me now. Maybe I can help someone coming from google or from somewhere else....

    - (NSNumber*) getPortnumber{
        int             port        = -1;
    
        CFSocketContext context;
        memset(&context, 0, sizeof(context));
        context.info = (__bridge void*)self;
    
        // Get Socket native handle from existing stream
        CFDataRef socketData = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)(_writeStream), kCFStreamPropertySocketNativeHandle);
    
        // Get the native handle
        CFSocketNativeHandle handle;
        CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), &handle);
    
        // Get the socket
        CFSocketRef cfSocket = CFSocketCreateWithNative(NULL, handle, kCFSocketNoCallBack, nil, &context);
    
        // CFSocketCopyAddress will return the address of the socket
        CFDataRef               dataRef = CFSocketCopyAddress(cfSocket);
        struct sockaddr_in      *sockaddr = (struct sockaddr_in*)CFDataGetBytePtr(dataRef);
    
        // Get the port from the address information
        port = sockaddr->sin_port;
    
        // Output Objective-C friendly =)
        NSNumber *portnr = [NSNumber numberWithInt:port];
        return portnr;
    }