Первые попытки HTTP POST и GET всегда медленные. Это связано с ОС или с сетью?

Теперь я только начал погружаться в HTTP. Я измерял время простых HTTP-запросов, используя GET и POST. Веб-страница, которую я использовал, представляет собой 3-строчную проверку php на правильность $_GET[] и $_POST[], а затем просто повторяет символ «1». Я использую POST и GET с одной и той же короткой парой имя/значение, надеясь, что не будет необходимости в фрагментации пакетов, чтобы все испортить, и все это делается в потоке, который отключен от потока пользовательского интерфейса. Запросы зацикливаются на телефоне несколько раз во время их хронометража. Все работает хорошо. (см. код ниже) То есть я получаю ответ «1». Но есть постоянная проблема со временем. Я наблюдаю следующее:

  1. При первой попытке время выполнения запроса намного больше, чем последующие попытки как в методах GET, так и в POST.

  2. Остальные попытки всегда намного быстрее для обоих.

  3. GET всегда быстрее, чем POST.

Все это верно для подключения 3G и Wi-Fi (но Wi-Fi в целом намного быстрее, как и ожидалось).

Я пробовал это с BasicResponseHandler() и с более ручными методами Buffered IO Stream с теми же результатами.

Кажется, я понимаю 3. как результат того, что для POST требуется две передачи: одна для возврата «HTTP 100», а затем тело пакета.- Это правильно?

Мой основной вопрос: что происходит с такими медленными первыми попытками запроса? Иногда это занимает несколько секунд(!). Это сеть, которая держит вещи, или Android помещает ее в сокет, создавая какую-то очередь? Если это Android, есть ли способ более правильно кодировать и избежать этого? Есть ли что-то в том, чтобы держать сокет открытым, чтобы сделать это проблемой только один раз во время выполнения? Если да, то является ли это хорошей практикой? По общему признанию, в этом аспекте я ничего не смыслю.

Я нашел несколько обсуждений по этому поводу, но ни одно из них не касалось этого аспекта напрямую.

--

Базовый код для методов GET и POST выглядит следующим образом (за вычетом try/catches) и выполняется в потоке вне пользовательского интерфейса, сначала метод GET, затем метод POST: (вывод ниже )

GET часть:

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

И версия 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

Они вызываются:

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

и:

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

С 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);
 }
};

и,

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);
 }
};  

Вывод обычно:

(0) GET-циклический обход составил 368 мс.

(1) Обратный путь GET составил 103 мс.

(2) Обратный путь GET составил 98 мс.

(3) Обратный путь GET составил 106 мс.

(4) Обратный путь GET составил 102 мс.


(0) POST-Tround Trip составил 1289 мс.

(1) Время прохождения POST-туда и обратно составило 567 мс.

(2) POST-Tround Trip составил 589 мс.

(3) POST-Tround Trip составил 496 мс.

(4) POST-Tround Trip составил 557 мс.

6
задан Tam 13 June 2012 в 05:31
поделиться