udp didReceiveData receiving two times

2.4k Views Asked by At

I have the problem that I send an udp Message (broadcast) to a client and get an answer, but this will be displayed two times. When I check the communication an my PC with an UDP listener there is only one message.

May be, someone can give me an info how I can resolve this.

I am using a button to start sending the message!

#import "ViewController.h"
#import "GCDAsyncUdpSocket.h"

@interface ViewController ()
{
    long tag;
    GCDAsyncUdpSocket *udpSocket;

}

@end

@implementation ViewController

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

    NSError *error = nil;

    if (![udpSocket bindToPort:1000 error:&error])
    {
        NSLog(@"Error binding: %@", error);
        return;
    }
    if (![udpSocket beginReceiving:&error])
    {
        NSLog(@"Error receiving: %@", error);
        return;
    }

    [udpSocket enableBroadcast:YES error: &error];

    NSLog(@"Ready");
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    if (udpSocket == nil)
    {
        [self setupSocket];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)send:(id)sender{
    NSString *host = @"192.168.2.255";
    if ([host length] == 0)
    {
        NSLog(@"Address required");
        return;
    }

    NSLog(@"%@",host);

    int port = 8888;

    NSString *msg = @"1,0,1,2";

    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    [udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:tag];

    NSLog(@"SENT (%i): %@", (int)tag, msg);

    tag++;

}

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
        fromAddress:(NSData *)address
        withFilterContext:(id)filterContext
{
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    if (msg)
    {
        NSLog(@"RECV: %@", msg);
        tag++;
        NSLog(@"%li",tag);
    }
    else
    {
        NSString *host = nil;
        uint16_t port = 0;
        [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];

        NSLog(@"RECV: Unknown message from: %@:%hu", host, port);
    }
}

@end

Here ist the output!

2013-09-11 09:49:00.132 udptest[5145:907] 15
2013-09-11 09:49:08.218 udptest[5145:907] 192.168.2.255
2013-09-11 09:49:08.220 udptest[5145:907] SENT (15): 1,0,1,2
2013-09-11 09:49:08.319 udptest[5145:907] RECV: 0,0,0,0,0,0,0,0
2013-09-11 09:49:08.321 udptest[5145:907] 17
2013-09-11 09:49:08.323 udptest[5145:907] RECV: 0,0,0,0,0,0,0,0
2013-09-11 09:49:08.324 udptest[5145:907] 18

I would be very grateful if someone could help me.

2

There are 2 best solutions below

1
Manoj Pandey On

Are the response message and the request message same in terms of what they contain. If yes, then here is one scenario that you might be running into. May be the first packet is the broadcast that you are listening for your self and the second packet is the response. To be more precise, when you send a broadcast (pkt p1), then the sender can also get a copy of p1. Next, when the receiver sends a response (pkt p2), then you see the response as well.

So, how do we verify it. You can look at the senders address (UDP provides an option) and then check if it is your address or the address of the other host.

6
LucaM On

I have the same strange unwanted and unresolved behaviour: "sender" sends one broadcast UDP message and "receiver" gets two messagges.

I've investigated as much as I could and these are my findings:

1) Wireshark gets only one UDP message.

2) udpSocket:didReceiveData:fromAddress:withFilterContext: gets fired two times!

3) Parsing the "address" param with [GCDAsyncUdpSocket getHost:port:fromAddress:] results in host = ::ffff:192.168.1.118 the FIRST time while host = 192.168.1.118 the SECOND time.

Hope it would be helpful in some manner...

EDIT (with a possible SOLUTION)

The FIRST address (see points 2 and 3) is an actual IPv6 address. So I guess that the udpSocket:didReceiveData:... is fired two times beacuse the first time the sender is the IPv6 address and the second time the sender is the IPv4 address of the same address.

And so my solution is to enable only the IPv4 in the UDP socket:

[udpSocket setIPv4Enabled:YES];
[udpSocket setIPv6Enabled:NO];