Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to receive response of the sent UDP packets using GCDAsyncSocket

Tags:

I am making an app to send UDP packets in order to switch on a LED bulb. I have been able to perform all the actions when I am connecting to the Ad-hoc created by the Wifi bridge.

Now, I want to configure the Wifi bridge so that it can connect to my main router. I have the AT command set to perform this procedure but somehow I am not able to receive the response form the Wifi bridge for the commands which I am sending to it.

The procedure is as follows:-

  • Step 1 : Send UDP message to the LAN broadcast IP address of "10.10.100.255" and port of 48899 => "Link_Wi-Fi"
    All Wifi bridges on the LAN will respond with their details. Response is "10.10.100.254, ACCF232483E8"

  • Step 2 : (optional for changing settings on the wifi bridge): Then send "+ok" to the LimitlessLED Wifi Bridge. Send UDP message to the response IP address returned from step 1 "10.10.100.254" => "+ok"

  • Step 3 : (optional for changing settings on the wifi bridge): After that you may send AT commands (ending with \r\n) to the module.

The code for sending the UDP packets is as follows

-(void)configureWifi{

    counter++;
    NSString *host = @"10.10.100.255";
    if ([host length] == 0)
    {
        [self logError:@"Address required"];
        return;
    }

    int port = 48899; //[portField.text intValue];
    if (port <= 0 || port > 65535)
    {
        [self logError:@"Valid port required"];
        return;
    }
    NSString *msg = @"Link_Wi-Fi";
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"the message sent is %@", data);
    [udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:tag];

}

Now in order to setup the socket and to receive the data I am using these two delegate methods:

 - (void)setupSocket
{
    // Setup our socket.
    // The socket will invoke our delegate methods using the usual delegate paradigm.
    // However, it will invoke the delegate methods on a specified GCD delegate dispatch queue.
    // 
    // Now we can configure the delegate dispatch queues however we want.
    // We could simply use the main dispatc queue, so the delegate methods are invoked on the main thread.
    // Or we could use a dedicated dispatch queue, which could be helpful if we were doing a lot of processing.
    // 
    // The best approach for your application will depend upon convenience, requirements and performance.
    // 
    // For this simple example, we're just going to use the main thread.

    udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSError *error = nil;

    if (![udpSocket bindToPort:0 error:&error])
    {
        [self logError:FORMAT(@"Error binding: %@", error)];
        return;
    }
    if (![udpSocket beginReceiving:&error])
    {
        [self logError:FORMAT(@"Error receiving: %@", error)];
        return;
    }

    [self logInfo:@"Ready"];
}

and to Receive data this is the method which is note getting called after sending the UDP packets. This is the delegate method of the GCDAsyncUdpSocket class which I have used in my project in order to send and receive the UDP packets.

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
                                               fromAddress:(NSData *)address
                                         withFilterContext:(id)filterContext
{
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if (msg)
    {
        [self logMessage:FORMAT(@"RECV: %@", msg)];
    }
    else
    {
        NSString *host = nil;
        uint16_t port = 0;
        [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];

        [self logInfo:FORMAT(@"RECV: Unknown message from: %@:%hu", host, port)];
    }
}

Once I am able to receive the response I will be able to send the next AT commands in order to configure the Bridge.

Thanks. Any help will be appreciated.

like image 764
Yuyutsu Avatar asked Apr 18 '15 06:04

Yuyutsu


People also ask

Does UDP send a response packet?

UDP is completely stateless, so after firing off a packet the only way an application can expect a response is if it knows the other end is going to send one.

Does UDP have a response?

Many traditional UDP protocols, like DNS, are request-response based. Since there is no state associated with a higher level "connection", the server can restart, to upgrade or change configuration, without any problems.

Are UDP packets guaranteed to arrive?

UDP does not guarantee that your packets will arrive in order. (It does not even guarantee that your packets will arrive at all.) If you need that level of robustness you are better off with TCP.

Can I send and receive UDP from same port?

Once connected, a TCP socket can only send and receive to/from the remote machine. This means that you'll need one TCP socket for each client in your application. UDP is not connection-based, you can send and receive to/from anyone at any time with the same socket.


2 Answers

Here are the troubleshooting steps I recommend that you use :

1- I'm assuming you are using ARC so make sure that your udpSocket variable has a strong reference throughout the asynchronous communication. If it is being freed, then that could explain the absence of a callback.

2- Make sure the communication is really happening the way you think it is. Use a software such as Wireshark to capture the packets being exchanged on the network. This should allow you to confirm that your packets do get sent upon calling sendData: and it will also allow you to confirm whether or not you are getting a reply back.

3- Make sure you are using the GCDAsyncUdpSocket properly. Considering you want to broadcast a message, you shouldn't be calling bindToPort:error: in your setupSocket method. Instead you should be calling enableBroadcast:error:. Considering you also want to receive packets after broadcasting, you should use the connectToHost:onPort:error: method to change the state of the socket to allow for bidirectional communication. After that is done, you can replace your usage of sendData:toHost:port:withTimeout:tag: by sendData:withTimeout:tag:. Finally, you can call beginReceiving: so that the delegate gets called for any incoming packets.

4- If this still doesn't get you through it, I recommend that you read throughly the documentation of the GCDAsyncUdpSocket which is very well documented.

like image 65
Dalzhim Avatar answered Sep 24 '22 20:09

Dalzhim


You can trouble shoot the problem using Wireshark or any network capture tool. We use to work in similar kind of project where we used Wireshark extensively. If packet has reached device(Z-Wave ) it will send out some sort of Ack. this will help to make sure packets are getting out.

like image 24
VikkyG Avatar answered Sep 22 '22 20:09

VikkyG