2012-10-28 23 views
6

Mam urządzenie w sieci, które wysyła bardzo mały plik przez UDP. Aplikacja IOS, którą tworzę, jest odpowiedzialna za przeczytanie tych pakietów i wybrałem do tego celu użycie GCDAsyncUdpSocket. Plik jest wysyłany co pół sekundy, jednak nie odbieram go prawie tak często (otrzymuję tylko co 3-10 sekund).GCDAsyncUdpSocket na brakujących datagramach multicastowanych w systemie iOS

Myśląc, że to może być problem z urządzeniem, zacząłem monitorować ruch z Wireshark. Wygląda na to, że odzwierciedla to, co widziałem w mojej aplikacji, dopóki nie włączyłem "trybu monitorowania" w Wireshark, w którym to momencie przechwytywano każdy pakiet UDP. Ponadto symulator iOS zaczął otrzymywać wszystkie brakujące pakiety, ponieważ dzieli się kartą sieciową z komputerem Mac, na którym się rozwijam.

Czy istnieje sposób, aby włączyć "Tryb monitorowania" na urządzeniu z systemem iOS lub coś, czego mi brakowało, aby umożliwić dostęp do brakujących pakietów? Widzę również, że istnieje metoda ReadStream w GCDAsyncUdpSocket. Być może muszę użyć tego zamiast beginReceiving? Chociaż nie wiem, jak skonfigurować strumienie w Objective-C, jeśli tak jest.

Oto mój kod testu, jak jest teraz:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    NSLog(@"View Loaded"); 
    [self setupSocket];    
} 

- (void)setupSocket 
{ 
    udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; 
    NSError *error = nil; 
    if (![udpSocket bindToPort:5555 error:&error]) 
    { 
     NSLog(@"Error binding to port: %@", error); 
     return; 
    } 
    if(![udpSocket joinMulticastGroup:@"226.1.1.1" error:&error]){ 
     NSLog(@"Error connecting to multicast group: %@", error); 
     return; 
    } 
    if (![udpSocket beginReceiving:&error]) 
    { 
     NSLog(@"Error receiving: %@", error); 
     return; 
    } 
    NSLog(@"Socket Ready"); 
} 

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data 
     fromAddress:(NSData *)address 
withFilterContext:(id)filterContext 
{ 
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
    if (msg) 
    { 
     NSLog(@"RCV: %@", msg); 
    } 
    else 
    { 
     NSString *host = nil; 
     uint16_t port = 0; 
     [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address]; 
     NSLog(@"Unknown message from : %@:%hu", host, port); 
    } 
} 

rozwiązanie dla każdego, kto przychodzi szuka tu w przyszłości:

oparciu o odpowiedź ilmiacs męska, udało mi się znacznie zmniejszyć liczbę brakujących pakietów, wysyłając polecenie ping do docelowego urządzenia z systemem iOS. Korzystanie z komputera Mac, wpadłem to w terminalu -

sudo ping -i 0.2 -s 4 <Target IP> 

Teraz mam to działa z Mac pingowanie urządzenie iOS, mam zamiar zajrzeć do przykładów ping Apple iOS i zobaczyć, czy mogę mieć urządzenie ping sam w celu stymulacji własnego adaptera bezprzewodowego (127.0.0.1).

+0

zdajesz sobie sprawę, że pakiety UDP ** nie są ** gwarantowane, że zostaną dostarczone przez projekt? Twoja aplikacja musi być w stanie obsłużyć tę sprawę. –

+0

Tak, wiem, że UDP jest niewiarygodny, ale czy to naprawdę może być przyczyną tego, że wiele pakietów nie zostanie przechwyconych? Ponadto aplikacja otrzymuje każdy pakiet bez problemu, o ile karta sieciowa ma włączony tryb monitorowania. – Squatch

+0

@ Czy możesz sprawdzić, z którego urządzenia korzystałeś? –

Odpowiedz

12

Poprzez moją pracę nad aplikacjami sieciowymi dla urządzeń iOS ujawniłem, że ich karty sieciowe mają dwa różne tryby, nazwijmy je aktywnymi i pasywnymi. Nie udało mi się znaleźć żadnej dokumentacji na ten temat. Oto moje wnioski:

  1. Dopóki w trybie aktywnym, adapter jest dość elastyczny. Mam czas odpowiedzi 3-5 ms.

  2. Po pewnym czasie bezczynności karta sieciowa systemu iOS przechodzi z trybu aktywnego do pasywnego. Czas, w którym to nastąpi, zależy od rzeczywistego modelu urządzenia. IPad trzeciej generacji to około 200ms. Dla iPhone 4 jest to bardziej jak 50ms.

  3. Żądanie ping lub pakiet TCP przeniesie adapter z trybu pasywnego do aktywnego. Może to zająć od 50ms do 800ms, średnio około 200ms.

To zachowanie jest całkowicie odtwarzalne za pomocą poleceń ping. Na przykład.

ping -i 0.2 <ios-device-ip> 

ustawia interwał ping na 200ms i utrzymuje kartę sieciową mojego iPada w stanie aktywnym.

To zachowanie jest całkowicie zgodne z twoimi obserwacjami, jeśli adapter (częściej niż nie) ignoruje pakiety UDP w trybie pasywnym. Aktywność wireshark prawdopodobnie utrzymuje ją w trybie aktywnym, a następnie otrzymywał UDP.

Sprawdź, czy pomaga funkcja ping.

Prawdopodobnie można utrzymać kartę sieciową urządzenia iDevice w stanie aktywnym, otwierając i łącząc dwa gniazda na samym urządzeniu i regularnie wysyłając sobie pakiety. Wprowadziłoby to pewien minimalny narzut.

Dlaczego jabłko zdecydowało się wprowadzić taką funkcję, mogę tylko spekulować na temat. Prawdopodobnie jednak utrzymanie aktywnego adaptera kosztuje wystarczającą moc baterii, aby uzasadnić taki wybór projektu.

Mam nadzieję, że to pomoże.

+0

Hmmmm bardzo interesująca. Nigdy bym nie pomyślał, żeby tego spróbować. Spróbuję tego dziś wieczorem. – Squatch

+0

Tak, zastanawialiśmy się co do opóźnienia przez co najmniej miesiąc. ;-) – ilmiacs

+0

Udało się! Wciąż brakuje niektórych pakietów, ale jest to znikoma ilość. Dzięki wielkie. – Squatch

1

Miałem ten sam problem.

Zaczynając wskaźnika aktywności sieciowej rozwiązać ten problem dla mnie:

UIApplication* app = [UIApplication sharedApplication]; 
app.networkActivityIndicatorVisible = YES; 
0

Jeśli chcesz, aby ten pakiet na urządzeniu z iOS, można powiązać swoje urządzenie z iOS do Mac i zamontować adapter wifi używając shell command rvictl . Następnie możesz użyć wireshark, tcpdump itp. Do monitorowania ruchu w twoim interfejsie 802.11 na twoim urządzeniu z iOS.

Jeśli nie otrzymasz danych od 3 do 7 sekund - Najprawdopodobniej Twoje urządzenie przechodzi w tryb oszczędzania energii (IEEE PSM), który jest funkcją 802.11, która zasadniczo powoduje uśpienie bezprzewodowej karty sieciowej.
Tryb PSM can yield poor performance on devices - szczególnie w twoim przypadku, gdy co pół sekundy masz okresowe impulsy danych. Twój okresowy ping powoduje przebudzenie karty sieciowej.