Сообщение Android HttpPost не отправит полезную нагрузку по сети - PullRequest
5 голосов
/ 16 августа 2011

Я пытаюсь отправить простую строку в качестве содержимого сообщения HttpPost.

Проблема в том, что тело сообщения HttpPost никогда не попадает в провод.(Говорит о захвате Wireshark).Хотя заголовок выглядит очень хорошо (включая правильно рассчитанную Content-Length.

Вот как выглядит код:

String url = "http://1.2.3.4/resource";
HttpClient client = new DefaultHttpClient();
String cmd = "AT+AVLPOS\r\n";
StringEntity se = new StringEntity(cmd);
se.setContentType("text/plain");  

HttpPost request = new HttpPost(url);
request.setHeader("Content-Type","text/plain");
request.setEntity(se);

HttpResponse response = client.execute(request);
[...]

Строка должна быть в кодировке ASCII, но это подробноэтот пункт.

Вот что отображается в WireShark: -> обратите внимание, что строки, отмеченные знаком +, - это то, что отправлено, и - это то, что получено.

+POST /resource HTTP/1.1
+Content-Type: text/plain
+Content-Length: 11
+Host: 1.2.3.4
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
+Expect: 100-Continue

-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked

-4
-OK

Это то, что должен появиться (для этого написал очень простое консольное приложение на C #, оно просто работает):

+POST /resource HTTP/1.1
+Content-Type: text/plain
+Host: 1.2.3.4
+Content-Length: 11
+Expect: 100-continue
+Connection: Keep-Alive
+
-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked
-
+AT+AVLPOS
+
-4
-OK
-
-48
-$AVTMR,99999999,204810,A,1234.2218,N,0123.1051,E,0,20,150811,0,REQ*69
-
-0
-

Есть предложения?

1 Ответ

13 голосов
/ 17 августа 2011

Я понял это, и я кое-чему научился сегодня.

Короче говоря: отключите HTTP Post expect-continue рукопожатие HttpClient, установив один из его параметров , это отправит сообщение с запросом целиком в один блок.

//set up HttpPost request as before
HttpClient client = new DefaultHttpClient();
client.getParams().setBooleanParameter("http.protocol.expect-continue", false);
HttpResponse response = client.execute(request);
[...]

Теперь вот как я туда попал, может, это кому-нибудь когда-нибудь поможет.

Сначала я получил от HttpEntityWrapper и использовал его как свою сущность запроса, чтобы увидеть, что вызывается, когда, и обнаружил, что метод Entity writeTo(OutputStream) вообще никогда не вызывался .

Затем я начал смотреть, почему в случае «правильного» поведения запрос POST не отправлялся сразу, а вместо этого отправлялись заголовки запроса, затем получался заголовок ответа, ТОГДА тело запроса отправлено.

Все это связано с HTTP Post expect-continue рукопожатием. Узнайте больше об этом на Haacked . Если в запросе отправляется заголовок ожидаемого продолжения, сервер Http ДОЛЖЕН ответить сообщением 100 Continue, означающим «ОК, я приму ваше сообщение», или с ошибкой, остановив, возможно, длинное сообщение POST на его дорожках.

К сожалению, веб-сервер, с которым я работаю, является простой реализацией, работающей на чипе, и отправляет неправильный ответ (200 OK вместо 100 Continue).
Реализация .NET Http-клиента по умолчанию выглядит здесь более простительно: он обрабатывает сообщение 200 как 100 Continue, пожимает плечами и получает возможность отправить тело запроса.

Не так с реализацией Http-клиента Android (уровень API 7).

Затем я попытался полностью отключить рукопожатие expect-continue, чтобы HttpClient отправил весь запрос. К моему удивлению и радости, веб-сервер прекрасно справился с этой задачей и ответил с информацией, которую я хотел. Ура!

...