不能使用GCDAsyncSocket接收发送的UDP数据包的响应

时间:2021-04-02 23:58:24

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.

我正在开发一个应用程序来发送UDP数据包,以便打开LED灯泡。当我连接到无线网桥的临时创建时,我已经能够执行所有的动作。

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.

现在,我想配置Wifi桥,让它能连接到我的主路由器。我有一个AT命令集来执行这个过程,但是不知何故,我无法收到我发送给它的命令的Wifi桥接的响应。

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"

    步骤1:将UDP消息发送到“10.10.100.255”的局域网广播IP地址,48899的端口为>“Link_Wi-Fi”,局域网上的所有Wifi网桥都会对其详细信息进行响应。反应是“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"

    第二步:(可选择更改wifi网桥设置):然后发送“+ok”至无限制led wifi网桥。将UDP消息发送到步骤1“10.10.10.100.254”返回的响应IP地址=>“+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.
  • 第三步:(可选择更改wifi网桥上的设置):之后您可以向模块发送AT命令(以\r\n结尾)。

The code for sending the UDP packets is as follows

发送UDP数据包的代码如下

-(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.

为了接收数据,这是在发送UDP数据包后被调用的方法。这是GCDAsyncUdpSocket类的委托方法,我在我的项目中使用它来发送和接收UDP数据包。

- (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.

一旦我能够接收到响应,我将能够发送下一个AT命令,以便配置桥接。

Thanks. Any help will be appreciated.

谢谢。如有任何帮助,我们将不胜感激。

2 个解决方案

#1


2  

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.

1-我假设您正在使用ARC,所以请确保您的udpSocket变量在整个异步通信过程中都具有强引用。如果它被释放,那么这可以解释为什么没有回调。

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.

2-确保交流是以你认为的方式进行的。使用像Wireshark这样的软件来捕获在网络上交换的数据包。这应该允许您确认,在调用sendData时,您的数据包确实被发送了:并且它还允许您确认是否正在收到回复。

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.

确保您正在正确地使用GCDAsyncUdpSocket。考虑到您希望广播消息,您不应该调用bindToPort:error:在setupSocket方法中。相反,您应该调用enableBroadcast:error:。考虑到您还希望在广播之后接收数据包,您应该使用connectToHost:onPort:error:方法来更改套接字的状态,以允许双向通信。完成之后,您可以替换您对sendData:toHost:port:withTimeout:tag: by sendData:withTimeout:tag:的使用。最后,您可以调用beginreceive:以便对任何传入的数据包调用委托。

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.

4-如果这仍然不能让您通过它,我建议您通读GCDAsyncUdpSocket的文档,它有很好的文档说明。

#2


1  

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.

您可能无法使用线鲨或任何网络捕获工具来解决这个问题。我们曾在类似的项目中工作,我们广泛地使用了线鲨。如果数据包已经到达设备(z波),它将发出某种Ack。这将有助于确保包被取出。

#1


2  

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.

1-我假设您正在使用ARC,所以请确保您的udpSocket变量在整个异步通信过程中都具有强引用。如果它被释放,那么这可以解释为什么没有回调。

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.

2-确保交流是以你认为的方式进行的。使用像Wireshark这样的软件来捕获在网络上交换的数据包。这应该允许您确认,在调用sendData时,您的数据包确实被发送了:并且它还允许您确认是否正在收到回复。

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.

确保您正在正确地使用GCDAsyncUdpSocket。考虑到您希望广播消息,您不应该调用bindToPort:error:在setupSocket方法中。相反,您应该调用enableBroadcast:error:。考虑到您还希望在广播之后接收数据包,您应该使用connectToHost:onPort:error:方法来更改套接字的状态,以允许双向通信。完成之后,您可以替换您对sendData:toHost:port:withTimeout:tag: by sendData:withTimeout:tag:的使用。最后,您可以调用beginreceive:以便对任何传入的数据包调用委托。

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.

4-如果这仍然不能让您通过它,我建议您通读GCDAsyncUdpSocket的文档,它有很好的文档说明。

#2


1  

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.

您可能无法使用线鲨或任何网络捕获工具来解决这个问题。我们曾在类似的项目中工作,我们广泛地使用了线鲨。如果数据包已经到达设备(z波),它将发出某种Ack。这将有助于确保包被取出。