5

我有一个问题,我向客户端发送 udp 消息(广播)并获得答案,但这将显示两次。当我检查我的 PC 与 UDP 侦听器的通信时,只有一条消息。

可能是,有人可以给我一个信息,我该如何解决这个问题。

我正在使用一个按钮开始发送消息!

#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

这是输出!

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

如果有人可以帮助我,我将不胜感激。

4

2 回答 2

13

我有同样奇怪的不需要和未解决的行为:“发送者”发送一条广播 UDP 消息,“接收者”收到两条消息。

我已经尽可能多地进行了调查,这些是我的发现:

1) Wireshark 只收到一条 UDP 消息。

2) udpSocket:didReceiveData:fromAddress:withFilterContext: 被触发两次!

3) 使用 [GCDAsyncUdpSocket getHost:port:fromAddress:] 解析“地址”参数会导致第一次host = ::ffff:192.168.1.118而第二次host = 192.168.1.118 。

希望它会以某种方式有所帮助......

编辑(可能的解决方案)

FIRST 地址(见第 2 点和第 3 点)是一个实际的 IPv6 地址。所以我猜 udpSocket:didReceiveData:... 被触发了两次,因为第一次发送者是 IPv6地址,第二次发送者是相同地址的 IPv4地址。

所以我的解决方案是在 UDP 套接字中只启用 IPv4:

[udpSocket setIPv4Enabled:YES];
[udpSocket setIPv6Enabled:NO];
于 2013-10-03T09:00:51.663 回答
0

就它们包含的内容而言,响应消息和请求消息是否相同。如果是,那么这是您可能遇到的一种情况。可能第一个数据包是您正在为自己收听的广播,而第二个数据包是响应。更准确的说,当你发送一个广播(pkt p1),那么发送者也可以得到一个p1的副本。接下来,当接收方发送响应 (pkt p2) 时,您也会看到响应。

那么,我们如何验证它。您可以查看发件人地址(UDP 提供了一个选项),然后检查它是您的地址还是其他主机的地址。

于 2013-09-11T16:01:59.067 回答