udp didReceiveData получает два раза
У меня проблема в том, что я отправляю сообщение udp (широковещательную рассылку) клиенту и получаю ответ, но это будет отображаться два раза. Когда я проверяю связь моего ПК с прослушивателем 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
Буду очень признателен, если кто-нибудь сможет мне помочь.
2 ответа
У меня такое же странное нежелательное и неразрешенное поведение: "отправитель" отправляет одно широковещательное UDP-сообщение, а "получатель" получает два сообщения.
Я исследовал столько, сколько мог, и вот мои выводы:
1) Wireshark получает только одно UDP-сообщение.
2) udpSocket: didReceiveData: fromAddress: withFilterContext: увольняется два раза!
3) Анализ параметра "address" с помощью [GCDAsyncUdpSocket getHost:port:fromAddress:] приводит к host =::ffff:192.168.1.118 в ПЕРВЫЙ раз, а host = 192.168.1.118 во ВТОРОЙ раз.
Надеюсь, это будет полезно в некотором роде...
РЕДАКТИРОВАТЬ (с возможным РЕШЕНИЕМ)
ПЕРВЫЙ адрес (см. Пункты 2 и 3) является фактическим адресом IPv6. Поэтому я предполагаю, что udpSocket:didReceiveData:... запускается два раза, поскольку в первый раз отправитель является IPv6- адресом, а второй раз - отправителем IPv4- адресом того же адреса.
И поэтому мое решение состоит в том, чтобы включить только IPv4 в сокете UDP:
[udpSocket setIPv4Enabled:YES];
[udpSocket setIPv6Enabled:NO];
Являются ли ответное сообщение и сообщение запроса одинаковыми с точки зрения того, что они содержат. Если да, то вот один сценарий, с которым вы можете столкнуться. Может быть, первый пакет - это широковещательная рассылка, которую вы слушаете для себя, а второй - ответ. Точнее говоря, когда вы отправляете широковещательную рассылку (pkt p1), отправитель также может получить копию p1. Затем, когда получатель отправляет ответ (pkt p2), вы также видите ответ.
Итак, как мы можем это проверить. Вы можете посмотреть адрес отправителя (UDP предоставляет опцию), а затем проверить, является ли он вашим адресом или адресом другого хоста.