udp didReceiveData 接收两次
Posted
技术标签:
【中文标题】udp didReceiveData 接收两次【英文标题】:udp didReceiveData receiving two times 【发布时间】:2013-09-11 08:46:16 【问题描述】:我有一个问题,我向客户端发送了一条 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
如果有人可以帮助我,我将非常感激。
【问题讨论】:
【参考方案1】:我有同样奇怪的不需要和未解决的行为:“发送者”发送一条广播 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];
【讨论】:
感谢您的编辑,IPv4 和 IPv6 工作正常! 为我工作问得很好。感谢您解决这个问题。 我遇到了完全相同的问题,这解决了它...顺便说一句,无需致电setIPv4Enabled
,默认情况下 - 只需禁用 IPv6。对我来说,这是客户端和服务器是同一台机器的副作用。我猜单个发送的消息会通过物理网络适配器和环回接口发出,因此GCDAsyncUdpSocket
会收到两次。
这是一个非常巧妙的观察。一定要为此投票!
也适合我。 setIPv6Enabled(false) 应该在调用 .beginReceiving() 之前调用,否则 didReceive 仍然会被触发两次。【参考方案2】:
响应消息和请求消息在它们包含的内容方面是否相同。如果是,那么这是您可能遇到的一种情况。可能第一个数据包是您正在为自己收听的广播,而第二个数据包是响应。更准确的说,当你发送一个广播(pkt p1),那么发送者也可以得到一个p1的副本。接下来,当接收方发送响应 (pkt p2) 时,您也会看到响应。
那么,我们如何验证它。您可以查看发送者地址(UDP 提供了一个选项),然后检查它是您的地址还是其他主机的地址。
【讨论】:
感谢您的回复。我明天试试,给个反馈。以上是关于udp didReceiveData 接收两次的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Multipeer Connectivity (Swift 3) 在会话中通过 didReceiveData() 调用 table.reloadData
使用 NSURLSession 时无法调用 didReceiveData