2012-06-13 17 views
6

Właśnie zacząłem dostawać moje stopy mokre w HTTP. Był czas timing proste żądania HTTP przy użyciu GET i POST. Strona, której użyłem, to 3-liniowy sprawdzian php dla poprawnych $ _GET [] i $ _POST [], a następnie po prostu echo znaku "1". Używam POST i GET z tą samą, pojedynczą krótką parą nazwa/wartość, mając nadzieję, że nie będzie potrzeby fragmentacji pakietów, aby wszystko było mylne, a wszystko to dzieje się w wątku, który jest wyłączony z wątku UI. Żądania są zapętlone w telefonie kilka razy, podczas gdy ich czas. Wszystko działa dobrze. (Zobacz poniższy kod), czyli otrzymuję odpowiedź "1". Istnieje jednak problem z utrzymaniem czasu. Co ja obserwować to, że:Pierwsze próby HTTP POST i GET są zawsze powolne - czy ten system operacyjny jest powiązany z siecią?

  1. W pierwszej próbie czasu, aby wniosek jest znacznie dłuższa niż kolejnych co¶ w obu metod GET i POST.

  2. Reszta prób jest zawsze szybsza dla obu.

  3. GET jest zawsze szybszy niż POST.

Wszystko to dotyczy połączeń 3G i Wi-Fi (ale w przypadku Wi-Fi jest znacznie szybsze, niż oczekiwano).

Próbowałem tego z BasicResponseHandler(), a także z bardziej ręcznie buforowanymi metodami IO Stream z tymi samymi wynikami.

Uważam, że rozumiem 3. jako wynik, że POST wymaga dwóch transmisji, jedna dla powrotu "HTTP 100", a następnie dla treści pakietu. - Czy to jest poprawne?

Moje główne pytanie brzmi: co dzieje się w pierwszych próbach, które są tak powolne? Czasami zajmuje to kilka sekund (!). Czy to sieć trzyma rzeczy, czy Android umieszcza ją w gnieździe, tworząc coś w rodzaju kolejki? Jeśli to Android, czy istnieje sposób na poprawne kodowanie i unikanie tego? Czy jest coś na temat trzymania otwartego gniazda, aby problem ten występował tylko raz podczas wykonywania? Jeśli tak, czy jest to dobra praktyka? Prawdą jest, że na tym punkcie nie mam pojęcia.

Znalazłem kilka dyskusji na ten temat, ale żaden nie uderzył bezpośrednio w ten aspekt.

-

kod podstawowy dla obu metod GET i POST wygląda następująco (minus try/połowów) i są wykonywane w wątku off UI, najpierw metody GET następnie metody POST: (wyjście poniżej)

GET część:

public String[] HTTPGETIt(int numrounds) 
{ 
HttpClient httpclient = new DefaultHttpClient(); 
httpclient.getParams().setParameter (CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1); 
HttpGet GETRequest = new HttpGet("http://mypage.com/epoch.php?mynameis=tam"); 
ResponseHandler <String> MyBRH = new BasicResponseHandler(); 
String[] GETResult = new String[numrounds]; 

int i = 0; 
long timestart, DT; 
while(i < numrounds) 
{ 
    timestart = System.currentTimeMillis(); 
    GETResult[i] = httpclient.execute(GETRequest, MyBRH); 
    DT = System.currentTimeMillis() - timestart; 
    Log.d(TAG, "(" + i + ") GET-Round Trip was "+ DT + " ms."); 
    i++; 
}//while i <= numrounds 
httpclient.getConnectionManager().shutdown(); 
return GETResult; 
} //END HTTPGETIt 

a wersja POST:

public String[] HTTPPOSTIt(int numrounds) 
{ 
String Place = "HTTPPostping"; 
HttpClient httpclient = new DefaultHttpClient(); 
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1); 
HttpPost PostRequest = new HttpPost("http://mypage.com/epoch.php"); 
ResponseHandler <String> MyBRH = new BasicResponseHandler(); 
String[] POSTResult = new String[numrounds]; 

List<NameValuePair> MynameValuePairs = new ArrayList<NameValuePair>(2); 
MynameValuePairs.add(new BasicNameValuePair("mynameis", "tam")); 

PostRequest.setEntity(new UrlEncodedFormEntity(MynameValuePairs)); 

int i = 0; 
long timestart, DT; 
while(i < numrounds) 
{ 
    timestart = System.currentTimeMillis(); 
    POSTResult[i] = httpclient.execute(PostRequest, MyBRH); 
    DT = System.currentTimeMillis() - timestart; 
    Log.d(TAG, "(" + i + ") POST-Round Trip was "+ DT + " ms."); 
    i++; 
}//while i <= numrounds 
httpclient.getConnectionManager().shutdown(); 
return POSTResult; 
} // END HTTPPOSTIt 

Są to tak zwane przez:

Runnable HTTPGETJob = new HTTPGETTask(NS); 
Thread HTTPGETThread = new Thread(HTTPGETJob, "HTTPGETThread"); 
HTTPGETThread.setPriority(Thread.MAX_PRIORITY); 
HTTPGETThread.start(); 

oraz:

Runnable HTTPPOSTJob = new HTTPPOSTTask(NS); 
Thread HTTPPOSTThread = new Thread(HTTPPOSTJob, "HTTPPOSTThread"); 
HTTPPOSTThread.setPriority(Thread.MAX_PRIORITY); 
HTTPPOSTThread.start(); 

Z runnables:

class HTTPGETTask implements Runnable 
{ 
int numtimes; 
DeviceInfo tsrtDI; 
HTTPGETTask(int inNS) { 
    this.numtimes = inNS; 
} 

@Override 
public void run() 
{ 
    long [] TT2NS = new long[numtimes]; 
    TT2NS = HTTPGETIt(numtimes); 
} 
}; 

oraz,

class HTTPPOSTTask implements Runnable 
{ 
int numtimes; 
DeviceInfo tsrtDI; 
HTTPPOSTTask(int inNS) { 
    this.numtimes = inNS; 
} 

@Override 
public void run() 
{ 
    long [] TT2NS = new long[numtimes]; 
    TT2NS = HTTPPOSTIt(numtimes); 
} 
}; 

Wyjście to zazwyczaj:

(0) GET-Round Trip miał 368 ms.

(1) Podróż GET w obie strony wynosiła 103 ms.

(2) GET-Round Trip było 98 ms.

(3) Podróż GET w obie strony wynosiła 106 ms.

(4) GET-Round Trip wyniósł 102 ms.


(0) POST-Round Trip to 1289 ms.

(1) POST-Round Trip miał 567 ms.

(2) POST-Round Trip miał 589 ms.

(3) POST-Round Trip miał 496 ms.

(4) POST-Round Trip miał 557 ms.

+0

Po pierwszym żądaniu wyniki mogą być buforowane –

+0

może rozdzielczość dns? spróbuj adresu IP – goat

+0

@rambo Po prostu wypróbowano jawny adres IP z takimi samymi wynikami. – Tam

Odpowiedz

1

Chciałbym nalegać, aby ustawić Protocol Version jako HTTP 1.1 i spróbować. Zwiększyłoby to czas żądania/odpowiedzi w porównaniu z tym, co teraz zajmuje. Nie próbowałem tego, właśnie dostałem informację. Przed wykonaniem żądania możesz wypróbować coś podobnego.

httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, 
                 HttpVersion.HTTP_1_1); 
+0

Po prostu to wypróbował, cera, bez zmian. Właśnie zaktualizowałem kod, który opublikowałem, aby go zawrzeć, tylko po to, aby był kompletny. Dzięki za sugestię. – Tam

1

zgadzam się z Lalit Poptani za Odpowiedź, które mogą pomóc, aby szybsze połączenia, ponieważ wydaje się być fakt, HTTP 1.1 utrzymuje połączenie i nie zrobić ręcznie wstrząsnąć każdym razem.

Ale jednocześnie chciałbym powiedzieć, że nie jest to problem specyficzny dla Androida, to samo dzieje się na prawie każdej platformie i w każdym języku, ponieważ po raz pierwszy podczas wykonywania połączenia http platforma musi zostać utworzona i ustaw różne obiekty, które przypisują mu wartości do wykonania połączenia, i które pozostaje w nim, więc kiedy nawiązujesz nowe połączenie, zapisywany jest czas na tworzenie i przypisywanie obiektów, dzięki czemu uzyskujesz szybsze odpowiedzi.

Który to obiekt? - to powiedziane w powyższych linijkach: Nie mam żadnej dość jasnej listy tych, ale są one jak ustawienia proxy, pamięć podręczna dla niego.


czekaj jeszcze, aż pojawi się ktoś z głęboką wiedzą techniczną na ten temat i wyjaśni, jak wszystko działa.

+0

Dziękuję. Nie robiłem tego rodzaju programowania w żadnym innym systemie operacyjnym, z którym pracowałem. – Tam