2015-05-07 12 views
8

W mojej aplikacji na iOS, mam funkcję wyszukiwania, która pobiera wyniki z serwera. Aktualizacje wyszukiwania są aktualizowane, gdy użytkownik aktualizuje zapytanie, co powoduje, że kilka żądań jest wykonywanych kolejno.iOS i Go - Keep-Alive przy użyciu NSURLSession

Moje pytanie brzmi: w jaki sposób mogę zagwarantować, że protokół TCP keep-alive jest używany w tych połączeniach? Chciałbym zmniejszyć jak najwięcej opóźnień, dlatego ważne jest, aby połączenie zostało utrzymane po pierwszym żądaniu i ponownie użyte dla następujących żądań.

Używam NSURLSession i słyszałem, że domyślnie zatrudnia ona tryb życia, ale skąd mogę wiedzieć na pewno? Rejestrowanie żądań na serwerze nie wykazuje żadnej różnicy między kolejnymi żądaniami, ale nie spodziewałbym się zobaczyć żadnych zmian bezpośrednio z informacji nagłówka.

Każda pomoc tutaj? Używam Go na moim serwerze, więc możliwe, że potrzebuje dodatkowej konfiguracji po tej stronie.

Odpowiedz

6

Wydaje mi się, że masz problem z utrzymaniem protokołu TCP z utrzymaniem aktywności protokołu HTTP (połączenia trwałe). Są to niepowiązane pojęcia. Z twojego pytania wynika prawdopodobnie trwałe połączenie HTTP.

W HTTP/1.1 połączenia trwałe są domyślne i są używane przez NSURLSession i prawie każdego klienta HTTP/1.1. Musisz poprosić o ich wyłączenie. Możesz sprawdzić numer Connection: close w nagłówku HTTP, lub po stronie serwera, możesz sprawdzić pole Close z . Ale jestem pewien, że otrzymujesz trwałe połączenia. Oznacza to, że nie trzeba renegocjować tunelu TLS (lub przynajmniej trójstopniowego uzgadniania TCP) dla każdego żądania. (Chociaż w przypadku równoległych żądań nadal będzie istniało wiele połączeń, które trzeba będzie negocjować, protokół HTTP/1.1 może obsłużyć tylko jedną rzecz naraz, a NSURLSession spróbuje użyć puli połączeń w celu skrócenia czasu odpowiedzi.)

Utrzymywanie aktywności TCP to zupełnie inna sprawa. Wysyła okresowe "ping" na drugą stronę, aby upewnić się, że jest jeszcze dostępny. Istnieje wiele sposobów na utratę połączenia sieciowego i nieznajomość go, dopóki następnym razem nie spróbujesz się komunikować, a normalnym objawem jest to, że połączenie po prostu się zawiesza i musisz je wyłączyć. Teoretycznie utrzymanie TCP-keep jest tylko narzędziem do odkrywania tego, ale prawie nigdy nie znalazłem tego w praktyce. Jest to trudne do prawidłowego skonfigurowania (szczególnie w Cocoa). Będziesz prawie zawsze potrzebował zbudować funkcjonalność "ping" wyższego poziomu dla swojej aplikacji, zamiast polegać na tym.

Ale wracając do twojego problemu, HTTP/1.1 jest prawdopodobnie w porządku dla Ciebie, ale będziesz musiał ostrożnie zarządzać swoimi odpowiedziami. Jeśli złożysz nowe żądanie na każdy list i odeślesz masywną odpowiedź, to będzie źle działać. Zamierzasz cały czas korzystać z puli połączeń, pobierając rzeczy, które zamierzasz wyrzucić. Najpierw musisz się skupić na dobrych algorytmach. Jako minimum, prawdopodobnie chcesz tylko wysłać kilka wyników jednocześnie i zapewnić w swoim API podejście "stronicowania", aby uzyskać więcej wyników dla tego samego wyszukiwania.

+0

Dzięki za pomocne informacje. Wprowadziłem kilka znaczących ulepszeń w algorytmie, ponieważ zadawano pytanie, co najważniejsze, wprowadzając zegar tak, że wyszukiwanie wysyła tylko żądanie, gdy użytkownik przestaje pisać przez chwilę. Ale ciekawi mnie podejście "stronicowania", o którym wspomniałeś - czy możesz wyjaśnić, co przez to rozumiesz? – hundley

+1

@hundley paging oznacza, że ​​jeśli jest więcej niż kilka wyników, zwracany jest tylko pierwszy zestaw, a późniejsze partie są pobierane przez dołączenie zmiennej żądania do żądanej strony. Zastanów się, jak wyniki Google pojawiają się w partiach. Ma to znaczenie tylko, jeśli liczba wyników może być oczywiście duża. Twoje "oczekiwanie na przerwę" to bardzo powszechna technika i bardzo pomocna. –

6

Aby wiedzieć na pewno, co robi TCP, można włączyć CFNETWORK_DIAGNOSTICS. Z dokumentacji:

Podczas normalnego programowania można ustawić tę zmienną środowiskową za pomocą edytora schematów Xcode. Jeśli chcesz zbadać problemy spoza Xcode, możesz ustawić programowo używając kodu pokazanego na Listingu 1.

Listing 1 programowe umożliwiające CFNetwork Rejestrowanie diagnostyczne

setenv("CFNETWORK_DIAGNOSTICS", "3", 1); 

Należy zrobić to prawo na początku sekwencji uruchomienie aplikacji. Zwykle umieszczenie tego na początku głównej jest wystarczające, ale jeśli masz statyczne inicjatory C++, które używają CFNetwork, będziesz musiał uruchomić je przed nimi.

CFNetwork rejestrowanie diagnostyczne rozpoczyna się przy pierwszym użyciu CFNetwork-ani żadnych ram, jak Fundacja, która używa CFNetwork-w tym momencie zostanie wydrukowana wiadomość takiego pokazany na listingu 2.

Listing 2 Przykładem komunikat uruchamiania rejestrowania diagnostycznego w sieci CFNet

2014-10-28 14:23:37.115 QTestbed[2626:60b] CFNetwork diagnostics log file created at: /private/var/mobile/Applications/76531F40-3291-4565-8C75-0438052C83BC/Library/Logs/CrashReporter/CFNetwork_com.example.apple-samplecode.QTestbed_2626.nwlrb 
Powiązane problemy