根据我对HTTP的理解,它的工作原理如下:客户端汇编一条消息,由一些头字段和(可能)一个主体组成,并将其发送到服务器。服务器处理它,组装自己的响应消息并将其发送回客户端。
所以我提出了这个问题:
为什么HttpURLConnection
中有突然的流?
这对我没有意义。它使它看起来像一个连续的开放通道。消息实际上在什么时候发送到服务器?在connect
?在getInputStream
?当试图从流中读取?如果我有有效载荷,它会在不同的时间发送吗?我可以只用一个连接进行写 - 读 - 写 - 读吗?
我确定我还没有理解它,但是现在它对我来说似乎是一个糟糕的API。
我希望看到更多这样的东西:
HttpURLConnection http = url.openConnection();
HttpMessage req = new HttpMessage;
req.addHeader(...);
req.setBody(...);
http.post(req);
// Block until response is available (Future pattern)
HttpMessage res = http.getResponse();
答案 0 :(得分:2)
虽然底层传输确实是使用单个数据包进行的,但并不能保证您认为单个http请求/响应的内容将适合"在一个http"数据包"。反过来,也不能保证单个http"数据包"将适合单个tcp数据包,依此类推。
想象一下使用http下载20MB的图像。它的单一http"响应"但我保证在浏览器和提供它的网站之间会有多个数据包来回传递。
每个块在每个级别都可能包含多个较小的块,并且因为您可能在它的所有不同位到达之前开始处理响应,并且您真的不想关注它们中有多少是,流是对此的共同抽象。
答案 1 :(得分:2)
恕我直言HttpURLConnection
确实有一个糟糕的API。但是将输入和输出消息作为流处理是一种有效处理大量数据的方法。我认为所有其他答案(此刻5!)都是正确的。有一些问题是开放的:
邮件在什么时候实际发送到服务器?在连接?在getInputStream?当试图从流中读取?
当所有收集的数据(例如标题,超时选项......)实际传输到服务器时,会有一些触发器。在大多数情况下,您不必致电connect
,这是隐含的,例如致电getResponseCode()
或getInputStream()
时。 (顺便说一下,我建议在getResponseCode()
之前调用getInputStream()
,因为如果您收到错误代码(例如404),getInputStream将抛出异常,您最好调用getErrorStream()
。)
如果我有有效载荷,它会在不同的时间发送吗?
您必须致电getOutputStream()
然后发送有效负载。在添加标题后(显然)应该这样做。关闭流后,您可以期待服务器的响应。
我可以只用一个连接进行写 - 读 - 写 - 读吗?
没有。从技术上讲,这可以在使用keep-alive
时实现。但是HttpURLConnection
在封面下处理这个问题,你只能用这个类的实例进行一次请求 - 响应往返。
让生活更轻松
如果您不想与HttpURLConnection
的可怕API进行斗争,您可以查看DavidWebb上列出的一些抽象API。使用DavidWebb
时,典型请求如下所示:
Webb webb = Webb.create();
String result = webb.post("http://my-server/path/resource")
.header("auth-token", myAuthToken)
.body(myBody)
.ensureSuccess()
.asString()
.getBody();
答案 2 :(得分:1)
这里Http协议适用于面向连接的TCP连接。所以在内部,它创建了一个TCP连接。然后发送http请求并接收回复。然后删除TCP连接。这就是为什么有两种不同的流。
答案 3 :(得分:1)
因为流是在Java中两个位置之间推送数据的通用方式,而这就是HTTP连接的作用。 HTTP通过TCP工作,这是一个流连接,所以这个API模仿它。
至于为什么它没有进一步抽象 - 考虑到HTTP请求中没有大小限制。例如,文件上传可以是许多MB甚至GB。
使用流式API,您可以从文件或其他来源读取数据,同时通过连接将其流式传输,而无需一次性将所有数据加载到内存中。
答案 4 :(得分:1)
流式响应可以动态消耗而不是分配本地内存中的所有数据,因此从内存的角度来看会更好,例如,如果你要解析一个巨大的json文件,从流和消耗后丢弃原始数据。从理论上讲,解析可以在第一个字节到达后立即开始。
发送/接收部分以及启动基础套接字的创建是getInputStream
答案 5 :(得分:1)
TCP 是一个字节流。 HTTP请求或响应的主体是任意字节流。不确定您期望的是哪种API,但是当您有字节流数据时,您将获得字节流API。