Android HttpPost 消息不会通过网络发送其有效负载

发布于 2024-11-29 13:33:43 字数 1328 浏览 1 评论 0原文

我正在尝试发送一个简单的字符串作为 HttpPost 消息的内容。

问题是,HttpPost 消息的正文永远不会到达线路。 (Wireshark 捕获说)。标头看起来不错(包括正确计算的内容长度)。

代码如下所示:

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
-

有什么建议吗?

I'm trying to send a simple string as the contents of a HttpPost message.

The problem is, the body of the HttpPost message never makes it to the wire. (Says the Wireshark capture). The header looks just fine though (including the correctly calculated Content-Length.

Here's what the code looks like:

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);
[...]

The string should be ASCII-encoded, but that's a detail at this point.

This is what shows up in WireShark:
-> note that lines marked with + are what's sent, and - is what's received.

+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

This is what should show up (wrote a very simple console app in C# to do this, it just works):

+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
-

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑饮青盏花 2024-12-06 13:33:43

我已经弄清楚了,今天我学到了一些东西。

长话短说:禁用 HttpClient 的 HTTP Post Expect-Continue 握手,通过 设置其参数之一,这将在一个块中发送整个请求消息。

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

现在这就是我到达那里的方法,也许有一天这会对某人有所帮助。

首先,我从 HttpEntityWrapper< /code>并使用它作为我的请求实体来查看何时调用什么,并发现 EntitywriteTo(OutputStream) 方法从未被调用过根本没有打电话。

然后我开始研究为什么在“正确”行为的情况下,POST 请求不是一次全部发送,而是发送请求标头,然后接收响应标头,然后请求正文是发送。

这一切都与 HTTP Post Expect-Continue 握手有关。阅读更多相关信息 被黑客攻击
如果在请求中发送了 Expect-Continue 标头,则 Http 服务器应该回复一个 100Continue 消息,表示“好的,我会接受你的消息”,或者返回一个错误,停止可能很长的 POST消息在其轨道上。

不幸的是,我运行的 Web 服务器是在芯片上运行的简单实现,它发送了错误的回复(200 OK 而不是 100 Continue)。
.NET Http 客户端的默认实现在这里似乎更加宽容:它将 200 消息视为 100 Continue耸耸肩,并获取正在发送请求正文。

Android 的 Http 客户端实现(API 级别 7)并非如此。

接下来我尝试的是完全禁用 expect-continue 握手,以使 HttpClient 发送整个请求。令我惊讶和高兴的是,网络服务器处理得很好,它回复了我想要的信息。耶!

I've figured it out, AND I've learned something today.

Long story short: disable the HttpClient's HTTP Post expect-continue handshake, by setting one of its parameters, this will send the whole request message in one chunk.

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

Now here's how I got there, maybe this will help someone someday.

First I derived from a HttpEntityWrapper and used that as my request entity to see what gets called when, and found out that the Entity's writeTo(OutputStream) method was never called at all.

Then I started to look at why, in the case of the "correct" behaviour, the POST request wasn't sent all at once, and instead, the request headers were sent, then the response header is received, THEN the request body is sent.

IT's all got to do with the HTTP Post expect-continue handshake. Read more about it on Haacked.
If the expect-continue header is sent in a request, the Http server SHOULD reply with a 100 Continue message signifying "OK, I will accept your message", or with an error, stopping the possibly long POST message in its tracks.

Unfortunately, the web server I run against is a bare bones implementation that runs on a chip, and it sends the wrong reply (200 OK instead of 100 Continue).
The default implementation of the .NET Http Client seems to be more forgiving here: it treats the 200 message as 100 Continue, shrugs, and gets on its way to send the request body.

Not so with the Http client implementation of Android (API level 7).

Next thing I tried was to disable the expect-continue handshake completely, in order to make the HttpClient send the whole request. To my surprise and joy, this was handled fine by the web server, which replied with the information I wanted. Yay!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文