2

google code question mirror: https://groups.google.com/forum/#!topic/cocoaasyncsocket/grhjZSMLr3U

here is my code that is reading the response:

- (void)init {
    udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSError *error = nil;
    if (![udpSocket bindToPort:UDP_PORT error:&error]) { //not connecting to host
        return;
    }
    if (![udpSocket beginReceiving:&error]) {
        return;
    }
}


- (void)udpSocket:(GCDAsyncUdpSocket *)sock
   didReceiveData:(NSData *)data
      fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"got data from broadcast: %@",msg);

    NSString *src = [[NSString alloc] initWithData:address encoding:NSUTF8StringEncoding];
    NSLog(@"got src from broadcast: %@",src); 
}

here is the code sending the udp bcast:

- (void)send {
    [udpSocket enableBroadcast:YES error:nil];
    [udpSocket sendData:[self pack:@"134.71.146.49"] toHost:UDP_BCAST_ADDR port:UDP_PORT withTimeout:-1 tag:UDP_BROADCAST_SEND];
}

port and bcast addr are 55555 and 255.255.255.255, respectively.

Console output:

got data from broadcast: 134.71.146.49
got src from broadcast: (null)

got data from broadcast: 134.71.146.49
got src from broadcast: (null)

hex:

 data:     <3133342e 37312e31 34362e34 39>
 address:  <1002d903 864793dd 00000000 00000000>

why is the source address here being null? Or why is it malformed?

jtbandes
  • 115,675
  • 35
  • 233
  • 266
stackOverFlew
  • 1,479
  • 2
  • 31
  • 58

1 Answers1

7

The address field return to you is actually a sockaddr_in structure flattened into an NSData object.

Here's the struct:

struct sockaddr_in {
    __uint8_t   sin_len;
    sa_family_t sin_family;
    in_port_t   sin_port;
    struct  in_addr sin_addr;
    char        sin_zero[8];
};

You can see from your display of the address object that the first field, sin_len, is 0x10, or 16 bytes. That's the length of the sockaddr_in struct. You can use that to tell if the address object refers to an IPv4 object or an IPv6 object. An IPv6 object would use the sockaddr_in6 struct and have a longer length.

You could copy that NSData object into a sockaddr_in struct, or just pull out the bytes at the right offset (4 through 7) to get the 4-byte source address that looks more familiar.

pixbug
  • 404
  • 3
  • 6
  • awesome! huge thanks. Unfortunately I'm no longer working on this project as it's been a year, but hope this helps someone in the future. – stackOverFlew Feb 25 '14 at 04:10
  • 1
    Yup, what I figured; thought I'd save others the trouble since I ended up digging through the library when I had the same issue. Please mark the answer as "accepted" if you'd be so kind. – pixbug Feb 26 '14 at 15:48
  • ohhhhooop sorry forgot! – stackOverFlew Feb 26 '14 at 21:08
  • I'm having the same problem - How would you go about casting the NSData object to a socked_in object? – cholewa1992 Apr 16 '15 at 19:53
  • 1
    @JacobBenjaminCholewa - briefly, I grab the pointer to the data in the NSData object, cast it to a sockaddr_in pointer, then pull out data from there, like this: `struct sockaddr_in *fromAddressV4 = (struct sockaddr_in *)address.bytes;` `char *fromIPAddress = inet_ntoa(fromAddressV4 -> sin_addr);` `iscoveredCamera.ipaddress = [[NSString alloc] initWithUTF8String:fromIPAddress];` – pixbug Apr 17 '15 at 22:25
  • Thanks! I will try that later today :-) – cholewa1992 Apr 18 '15 at 12:19