iOS 进阶

无法使用GCDAsyncSocket接收发送的UDP数据包的响应

2019-04-30  本文已影响0人  路漫漫其修远兮Wzt

转载自:无法使用GCDAsyncSocket接收发送的UDP数据包的响应?

场景:

客户端向服务端的端口A发送数据,服务端监听端口A;服务端接收到数据包(数据包里面包含客户端端口信息B)后,会向客户端端口B返回一个响应数据;

需求:

1.Android中使用socket.receive(data)可以直接接收到服务端的响应数据包;(参考Socket通信入门之基于UDP
2.iOS使用GCDAsyncSocket怎么接收服务端的响应数据呢?答案是绑定端口0[udpSocket bindToPort:0 error:&error],然后在代理方法-(void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext中接收服务端响应数据;(参考无法使用GCDAsyncSocket接收发送的UDP数据包的响应?)

以下是参考文献正文:

正在制作一个应用程序UDP数据包,以便打开LED bulb,当连接到Ad-hoc,通过Wifi bridge...

程序如下:

步骤1:向局域网广播IP地址10.10.100.255和端口48899=>“Link”发送UDP消息"Link_Wi-Fi" “ 局域网上的所有Wifi桥都将对其细节作出反应。答复为“10.10.100.254,ACCF 232483E8”
步骤2:(可选用于更改wifi桥上的设置):然后发送“+ok”到有限LED Wifi桥。将UDP消息发送到步骤1“10.10.100.254”=>“+ok”返回的响应IP地址
步骤3:(可选用于更改wifi桥上的设置):在此之后,您可以向模块发送AT命令(以\r\n结尾)。
发送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];

}

现在,为了设置套接字并接收数据,使用以下两个委托方法:

 - (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"];
}

为了接收数据,需要在发送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)];
    }
}

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

上一篇下一篇

猜你喜欢

热点阅读