天道酬勤,学无止境

使用 okhttp 分块的传输编码仅提供完整结果(Transfer Encoding chunked with okhttp only delivers full result)

问题

我正在尝试对分块端点获得一些见解,因此计划逐块打印服务器发送给我的内容。 我没有这样做,所以我写了一个测试,看看 OkHttp/Retrofit 是否按我的预期工作。

以下测试应该向控制台提供一些块,但我得到的只是完整的响应。

我什至让 OkHttp3 的 MockWebServer 向我发送块,我有点失去了我所缺少的东西。

我发现了这个改造问题条目,但答案对我来说有点模棱两可:Chunked Transfer Encoding Response

class ChunkTest {
    @Rule
    @JvmField
    val rule = RxImmediateSchedulerRule() // custom rule to run Rx synchronously

    @Test
    fun `test Chunked Response`() {
        val mockWebServer = MockWebServer()
        mockWebServer.enqueue(getMockChunkedResponse())

        val retrofit = Retrofit.Builder()
                .baseUrl(mockWebServer.url("/"))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(OkHttpClient.Builder().build())
                .build()
        val chunkedApi = retrofit.create(ChunkedApi::class.java)

        chunkedApi.getChunked()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    System.out.println(it.string())
                }, {
                    System.out.println(it.message)
                })

        mockWebServer.shutdown()
    }

    private fun getMockChunkedResponse(): MockResponse {
        val mockResponse = MockResponse()
        mockResponse.setHeader("Transfer-Encoding", "chunked")
        mockResponse.setChunkedBody("THIS IS A CHUNKED RESPONSE!", 5)
        return mockResponse
    }
}

interface ChunkedApi {
    @Streaming
    @GET("/")
    fun getChunked(): Flowable<ResponseBody>
}

测试控制台输出:

Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$2 execute
INFO: MockWebServer[49293] starting to accept connections
Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$3 processOneRequest
INFO: MockWebServer[49293] received request: GET / HTTP/1.1 and responded: HTTP/1.1 200 OK
THIS IS A CHUNKED RESPONSE!
Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$2 acceptConnections
INFO: MockWebServer[49293] done accepting connections: Socket closed

我希望更像(每 5 个字节“剪切”一次正文):

Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$2 execute
INFO: MockWebServer[49293] starting to accept connections
Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$3 processOneRequest
INFO: MockWebServer[49293] received request: GET / HTTP/1.1 and responded: HTTP/1.1 200 OK
THIS
IS A 
CHUNKE
D RESPO
NSE!
Nov 06, 2018 4:08:15 PM okhttp3.mockwebserver.MockWebServer$2 acceptConnections
INFO: MockWebServer[49293] done accepting connections: Socket closed
回答1

OkHttp Mockserver 确实对数据进行了分块,但是看起来 LoggingInterceptor 会等到整个块缓冲区已满,然后才会显示它。

从这个关于 HTTP 流的漂亮总结:

Transfer-Encoding: chunked 的使用允许在单个请求或响应中进行流式传输。 这意味着数据以分块方式传输,并且不会影响内容的表示。

考虑到这一点,我们正在处理 1 个“请求/响应”,这意味着我们必须在获得整个响应之前进行块检索。 然后将每个块推送到我们自己的缓冲区中,所有这些都在OkHttp network interceptor上。

这是所述NetworkInterceptor的示例:

class ChunksInterceptor: Interceptor {

    val Utf8Charset = Charset.forName ("UTF-8")

    override fun intercept (chain: Interceptor.Chain): Response {
        val originalResponse = chain.proceed (chain.request ())
        val responseBody = originalResponse.body ()
        val source = responseBody!!.source ()

        val buffer = Buffer () // We create our own Buffer

        // Returns true if there are no more bytes in this source
        while (!source.exhausted ()) {
            val readBytes = source.read (buffer, Long.MAX_VALUE) // We read the whole buffer
            val data = buffer.readString (Utf8Charset)

            println ("Read: $readBytes bytes")
            println ("Content: \n $data \n")
        }

        return originalResponse
    }
}

然后当然我们在 OkHttp 客户端上注册这个网络拦截器。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 使用 Transfer-Encoding 改造客户端和响应:分块(Retrofit client and response with Transfer-Encoding: chunked)
    问题 我正在开发一个从 http://www.omdbapi.com/ 获取电影列表的 Android 示例应用程序。 REST 服务是: http://www.omdbapi.com/?s=star&apikey=d497e644 我正在使用 Retrofit 编写客户端。 public interface OmdbApi { @Streaming @GET("./") @Headers({"Cache-control: no-cache"}) Call<Search> search(@Query("s") String search, @Query("apikey") String apiKey); @Streaming @GET("./") @Headers({"Cache-control: no-cache"}) Call<FilmDetail> getFilm(@Query("i") String uid, @Query("apikey") String apiKey); } 完整的源代码可在此处获得。 当我运行应用程序时,我获得以下响应(取自 logcat): OK http://www.omdbapi.com/?s=star&apikey=d497e644 (108ms) Content-Type: application/json; charset=utf-8
  • 内容长度标头与分块编码(Content-Length header versus chunked encoding)
    问题 我试图权衡设置Content-Length HTTP标头与使用分块编码从服务器返回[可能]大文件的利弊。 需要使用持久性连接之一来符合HTTP 1.1规范。 我看到Content-Length标头的优点是: 下载对话框可以显示准确的进度条客户预先知道文件是否可能太大,以至于他们无法提取 缺点是必须在返回对象之前计算大小,这并不总是很实际,并且可能会增加服务器/数据库的利用率。 分块编码的缺点是在每个分块和下载进度栏之前增加分块大小的小开销。 有什么想法吗? 对于我可能没有想到的两种方法,还有其他HTTP注意事项吗? 回答1 一定要使用Content-Length。 由此将几乎不存在服务器利用率,并且将为您的用户带来巨大的收益。 对于动态内容,添加压缩响应支持( gzip )也非常简单。 这需要输出缓冲,这又会为您提供内容的长度。 (不适用于文件下载或已压缩的内容(声音,图像))。 还考虑添加对部分内容/字节范围服务的支持-即重新启动下载的功能。 有关字节范围的示例,请参见此处(示例在PHP中,但适用于任何语言)。 提供部分内容时需要Content-Length。 当然,这些并不是灵丹妙药:对于流媒体,使用输出缓冲或响应大小是毫无意义的。 对于大文件,输出缓冲没有意义,但是Content-Length和字节服务意义重大(可以重新启动失败的下载)。 就个人而言,只要知道
  • 使用 XHR 和分块传输编码的 HTTP POST(HTTP POST using XHR with Chunked Transfer Encoding)
    问题 我有一个 REST API,它通过 HTTP Post 接受音频文件。 API 支持 Transfer-Encoding: 分块请求标头,以便文件可以在从客户端上运行的记录器创建时分块上传。 这样服务器就可以在文件到达时开始处理文件以提高性能。 例如: HTTP 1.1 POST .../v1/processAudio 传输编码:分块 [Chunk 1 256 Bytes](服务器到达时开始处理) [块 2 256 字节] [块 3 256 字节] ... 音频文件通常很短,大小在 10K 到 100K 左右。 我有可以工作的 C# 和 Java 代码,所以我知道 API 可以工作。 但是,我似乎无法使用 javascript 在浏览器中进行录制和上传。 这是我的测试代码,它使用 Transfer-Encoding 对 localhost 执行 POST: <html> <script type="text/javascript"> function streamUpload() { var blob = new Blob(['GmnQPBU+nyRGER4JPAW4DjDQC19D']); var xhr = new XMLHttpRequest(); // Add any event handlers here... xhr.open('POST', '/', true)
  • 如果传输编码被分块,如何使用java获取http响应中块的大小(how to get the size of chunk in http response using java if transfer encoding is chunked)
    问题 如果传输编码是分块的,如何知道 HTTP 响应块的大小。我无法获得逻辑。 请帮助我。并为我提供一些示例 java 代码来获取块的大小。我在一些书中读到,在块本身之前指定了每个块的大小。但是使用哪种逻辑我可以得到它。 请帮助我使用java。 谢谢你。 回答1 无法提供现成的代码,但 Apache HttpClient 库支持开箱即用的“一切”。 这是分块响应的维基百科示例。 在读取正文部分之前,您不知道数据的确切字节大小。 请注意每个块的大小是十六进制值,最后一个大小为 0 的块是数据的结尾。 它也由 2 字节 CRLF 分隔符终止。 Transfer-Encoding: chunked\r\n Content-Type: text/plain\r\n \r\n 4\r\n Wiki\r\n 5;extkey=extvalue\r\n pedia\r\n E\r\n .in\r\n \r\n chunks.\r\n 0\r\n AfterBodyHeader: some value\r\n AfterBodyHeader2: any value\r\n \r\n 读取字节直到 CRLF(\r\n 或 0D0A 十六进制) 之后放下一切; 分隔符或在尾随 CRLF 处停止,某些回复可能会在块大小行添加扩展名。 除非您等待已知的键值对,否则请忽略它们。 将十六进制转换为整数
  • HTTP Content-Length与分块传输
    HTTP Content-Length与分块传输 Content-Length是HTTP 请求用来告知body实体大小的一个字段。 比如Content-Length:1076表示 body数据量为1076B。 如果使用 gzip, 长度值为实际压缩后的大小,而非原始数据大小。 分块传输 分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由应用服务器发送给客户端应用的数据(通常数据量较大或者长度未告知,比如视频,文件文档,动态生成)可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。 使用Transfer-Encoding的chunked值表示数据以分块的形式发送,这种情况Content-Length通常不赋值。 比如 Content-Length:null Transfer-Encoding:chunked (接下来的body我要一块一块的传,每一块大小可能不一样,等我传到大小为0的块时,就没了) 优点 HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久连接。通常,持久链接需要服务器在开始发送消息体前发送Content-Length消息头字段,但是对于动态生成的内容来说,在内容创建完之前是不可知的。[动态内容,content-length无法预知
  • 使用 Node.JS 提供 HTTP/1.0 响应(未知内容长度,分块传输编码)(Serving HTTP/1.0 responses with Node.JS (unknown content length, chunked transfer encoding))
    问题 问题 我正在通过 Node.JS 提供未知长度的资源。 因此,无法设置Content-Length标头。 对于 HTTP 1.1,需要对这种性质的资源使用分块编码。 Node.JS 知道这一点,并通过自己的分块传输编码发送我的数据,并带有以下标头: HTTP/1.1 200 OK Transfer-Encoding: chunked Connection: close ... 这对行为端正的客户来说一切都很好。 但是,我必须支持一些表现不佳的客户端(即 Android 2.2 及更早版本)。 这些客户端不正确支持分块传输编码。 修复尝试 #1 我最初的想法是将编码设置为none如下所示: response.writeHead(200, {'Transfer-Encoding': 'none'}); 这会禁用 Node.JS 的自动分块编码并保持与大多数客户端的兼容性。 然而,现在我已经破坏了 Android 2.3+ 客户端,因为当他们看到这样一个虚假的传输编码头时,他们只是咳嗽和窒息。 修复尝试 #2(我需要帮助的地方) 当我使用HTTP/1.0发出请求时,服务器正确返回响应而不使用分块编码: HTTP/1.1 200 OK Connection: close ... 这解决了我的问题,并允许我为所有麻烦的客户提供服务。 我不必为Transfer
  • 传输编码:分块(Transfer-Encoding: chunked)
    问题 我试图了解更多关于Transfer-Encoding:chunked 。 引用了一些文章:http://zoompf.com/blog/2012/05/too-chunky 和 ​​PHP 中的“Transfer-Encoding:chunked”标题。 我仍然没有得到非常清晰的图片。 我了解设置此编码允许服务器将内容分块设置到浏览器,并在使网站响应时导致内容的部分呈现。 如果我有一个 Web 应用程序提供动态内容(例如:基于 JSF 的 Web 应用程序)托管在 IBM WAS 上,那么大多数网页都旨在为具有大量 CSS 和 JS 文件+动态内容的丰富静态内容提供服务。 如何为我的页面设置传输编码“分块”? 或者换句话说: 您如何决定哪个页面将具有'Transfer-Encoding: chunked'以及如何为该页面设置它? 你的个人经历对我的理解肯定很有价值。 回答1 Transfer-Encoding: chunked渐进式渲染不需要Transfer-Encoding: chunked 。 然而,当第一字节被发送之前的总含量长度未知它是需要的。 回答2 当服务器需要发送大量数据时,服务器使用分块编码,因为它并不确切知道数据将有多大(长度)。 在 HTTP 术语中,当服务器发送响应时,服务器会省略 Content-Length 标头。 相反
  • Tomcat gzip而分块问题(Tomcat gzip while chunked issue)
    问题 我的一项数据源服务遇到了一些问题。 正如它在 HTTP 响应头中所说的那样,它在 Apache-Coyote/1.1 上运行。 服务器使用 Transfer-Encoding: chunked 给出响应,这里是示例响应: HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/xml;charset=utf-8 Transfer-Encoding: chunked Content-Encoding: gzip Date: Tue, 30 Mar 2010 06:13:52 GMT 问题是当我请求服务器发送 gzipped 请求时,它经常发送不完整的响应。 我收到回复,看到收到的最后一块,但在解压缩后我看到回复是部分的。 我从未见过在请求标头中关闭 gzip 的这种行为。 所以我的问题是:这是常见的 tomcat 问题吗? 也许其中一个正在做压缩的mod? 或者它可能是某种代理问题? 我不知道 tomcat 的版本或他们使用什么 gzip mod,但请随意询问,我会尝试询问我的服务提供商。 谢谢。 回答1 由于 gzip 响应的内容长度是不可预测的,并且首先在内存中完全压缩它可能很昂贵且很慢,然后计算长度,然后从内存中流式传输 gzip 响应,一般的网络服务器将使用传输编码将它们分块发送:没有Content
  • 如何在 ASP.NET 响应中显式或隐式地将 Transfer-Encoding 设置为分块?(How can I set Transfer-Encoding to chunked, explicitly or implicitly, in an ASP.NET response? )
    问题 我可以简单地设置Transfer-Encoding标头吗? 在某些时候调用Response.Flush()会导致这种情况隐式发生吗? 编辑不,我不能调用Response.Headers.Add("Transfer-Encoding","anything"); 那抛出。 还有其他建议吗? 有关的: 在 ASP.NET 中启用分块传输编码 回答1 TL;DR:指定内容长度是实现快速首字节的最佳方式; 您将允许在 TCP 而不是 HTTP 级别进行分块。 如果您不知道内容长度,将context.Response.BufferOutput设置为false将发送输出,因为它使用分块传输编码写入输出流。 为什么要设置Transfer-Encoding: chunked ? 分块传输本质上是一种允许发送内容长度未知的文档的变通方法。 ASP.NET,但是,在默认情况下缓存整个输出,因此不知道整体内容长度。 当然,HTTP 是在 TCP 之上分层的,并且在幕后 TCP 无论如何都会通过将单一的 HTTP 响应拆分为数据包来“分块”——这意味着如果您预先指定内容长度并禁用输出缓冲,您将获得无需HTTP级分块最好的延迟。 因此,当您知道内容长度时,您不需要 HTTP 级分块来提供快速的第一个字节。 虽然我不是 HTTP 方面的专家,但我已经实现了一个简单的流媒体服务器,具有寻求支持、动态压缩
  • bigpipe 实现原理
    一、什么是 bigPipe?bigPipe 是由 facebook 提出来的一种动态网页加载技术。它将网页分解成称为 pagelets 的小块,然后分块传输到浏览器端,进行渲染。它可以有效地提升首屏渲染时间。为了说清楚什么是 bigPipe,我先需要介绍下目前的常规渲染方式,以及可以进行优化的方向。二、网页首屏加载方案(1)HTTP 协议的底层是 TCP/IP,而 TCP/IP 规定三次握手才建立一次连接。每一个新增的请求都要重新建立 TCP/IP 连接,从而消耗服务器的资源,而对于几种不同的服务器程序——Apache、Nginx、Node.js——所消耗的资源也不太一样。现有的阻塞模型(2)如上图,现有的阻塞模型中,服务器生成页面需要时间(page generation),网络传输需要时间(network latency),页面在浏览器中渲染需要时间(page rendering),三者是阻塞式的,整个页面作为一个大块,需要完整地经历三个阶段,才能出现在浏览器中。三、关键技术和原理想要实现以上优化方案,可以利用现成的技术,有比较好的兼容性。1.分段传输bigPipe 依赖于分段传输 html 页面,所以这是实现 bigPipe 的一个基础。http1.1如果在 http1.1 版本上实现,那需要设置 Transfer-Encoding 为 chunked,也就是分块传输编码
  • 服务器有时返回分块传输编码(server sometimes returns chunked transfer encoding)
    问题 我正在构建REST API。有时服务器使用分块传输编码返回响应? 这是为什么?! 为什么服务器不能总是以相同的编码返回响应? 问题是当块返回时,我不知道如何读取数据! 更新 neeore moore downvotes ... to breeeath ... 回答1 假设您的服务器使用的是Apache,则这是预期的行为。 您可以通过将以下行放在.htaccess文件中来禁用它: SetEnv downgrade-1.0 但是,您应该考虑修改阅读代码以仅支持不同的内容编码。 您正在使用哪个库来发出HTTP请求? 任何合理的HTTP库都可以处理分块的请求。 如果您的请求代码是用PHP编写的,请使用curl。 http://php.net/manual/zh/book.curl.php 回答2 取自服务器故障: 指定“ Content-Length”标头,以便服务器知道响应的大小是多少在请求方使用HTTP 1.0 回答3 问题可能是Apache正在压缩您的下载文件,以纠正Content-Length的问题,或者在您的情况下,添加标题 内容编码:分块 您可以添加.htaccess RewriteRule以禁用gzip: RewriteRule . - [E=no-gzip:1]
  • 分块编码(Transfer-Encoding: chunked)VS Content-length
    参考链接: HTTP 协议中的 Transfer-Encoding 分块传输编码 https://www.cnblogs.com/xuehaoyue/p/6639029.html 一、背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界;而对于持续连接,这种方法显然不奏效。有时,尽管我已经发送完所有数据,但浏览器并不知道这一点,它无法得知这个打开的连接上是否还会有新数据进来,只能傻傻地等了。用Content-length解决:计算实体长度,并通过头部告诉对方。浏览器可以通过 Content-Length 的长度信息,判断出响应实体已结束Content-length引入的新问题:由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界——分块编码(Transfer-Encoding: chunked) 二、分块编码(Transfer-Encoding: chunked) Transfer-Encoding,是一个 HTTP 头部字段(响应头域),字面意思是「传输编码」。最新的
  • 在 C#'WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据(Serving data with “transfer-encoding: chunked” on an ApiController in C#' WebAPI)
    问题 我需要使用ApiController提供分块传输编码数据。 因为我无权访问HttpContext或HttpRequest ,所以我不知道在哪里写入响应以及在哪里刷新它。 设置如下: public class MyController : ApiController { [Route("testing")] [HttpGet] public string Get() { ... return <response object ot HttpResponseMessage } } 我想我可能使用了错误的基类/框架/概念? 非常感谢! 回答1 您确实可以访问上下文和请求。 您需要访问响应: public string Get() { ActionContext.Response.Headers.TransferEncodingChunked = true; // ... }
  • nginx分块传输编码失败(nginx chunked transfer encoding fails)
    问题 我正在使用带有码头 servlet 的 nginx 实现。 出于我的项目的目的,我需要初始化到 jetty servlet 的两个连接并使它们保持打开状态。 为了初始化下行链路,我使用了一个普通的请求,然后我得到了输入流。 为了初始化上行链路,我使用分块编码请求。 我使用 1.4.6 nginx 版本,因此默认情况下应该设置分块编码,无论我在服务器定义中设置它。 #HTTPS server server { listen 443; listen [::]:443; server_name localhost; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_http_version 1.1; expires off; proxy_buffering off; chunked_transfer_encoding on; proxy_pass https://127
  • Web API 作为代理和分块传输编码(Web API as a Proxy and Chunked Transfer Encoding)
    问题 我一直在尝试使用 Web API(Web 主机)作为代理服务器,并且遇到了我的 Web API 代理如何处理带有“Transfer-Encoding: chunked”标头的响应的问题。 绕过代理时,远程资源会发送以下响应标头: Cache-Control:no-cache Content-Encoding:gzip Content-Type:text/html Date:Fri, 24 May 2013 12:42:27 GMT Expires:-1 Pragma:no-cache Server:Microsoft-IIS/8.0 Transfer-Encoding:chunked Vary:Accept-Encoding X-AspNet-Version:4.0.30319 X-Powered-By:ASP.NET 在通过基于 Web API 的代理时,除非我将响应标头上的 TransferEncodingChunked 属性显式重置为 false,否则我的请求会挂起: response.Headers.TransferEncodingChunked = false; 我承认,我不完全理解设置 TransferEncodingChunked 属性有什么影响,但对我来说似乎很奇怪,为了使代理按预期工作,我需要将此属性设置为 false 时显然传入的响应具有“传输编码:分块
  • Jersey/JAX-RS:在响应标头中返回 Content-Length 而不是分块传输编码(Jersey/JAX-RS : Return Content-Length in response header instead of chunked transfer encoding)
    问题 我正在使用 Jersey 来创建 RESTful API 资源,并使用ResponseBuilder来生成响应。 RESTful 资源的示例代码: public class infoResource{ @GET @Path("service/{id}") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getCompany(@PathParam("id")String id) { //company is just a POJO. Company company = getCompany(id); return Response.status(200).entity(company).build(); } } 在响应中,它在响应标头中返回分块传输编码。 “泽西世界”中让它返回Content-Length标头而不是Transfer-Encoding: chunked响应标头中的Transfer-Encoding: chunked标头的正确方法是什么? 回答1 选择Content-Length或Transfer-Encoding就是那些 Containers 的选择。 这实际上是缓冲区大小的问题。
  • 一文了解HTTP走私请求漏洞
    前言 之前听一位师傅提了一嘴HTTP走私请求漏洞,挺感兴趣,就学习了下 主要思想是利用前后端对消息结束位的分歧,在HTTP中隐藏HTTP,或者说将HTTP协议注入HTTP协议 一、基础知识 1、HTTP协议 HTTP(超文本传输协议): 一种无状态的、应用层的、以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动工作于客户端-服务端架构之上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息客户端和服务器之间进行http请求时,请求和响应都是一个数据包,它们之间是需要一个传输的通道的所以会先创建tcp连接,只有当tcp连接之后,才能发送http请求 HTTP1.0协议和HTTP1.1协议的一个重要不同: 在HTTP1.0里面,TCP连接是在HTTP请求创建的时候,就去创建这个TCP连接,然后连接创建完之后,请求发送过去,服务器响应之后,这个TCP连接就关闭了在HTTP1.1协议中,可以用Keep-Alive方法去申明这个连接可以一直保持,那么第二个HTTP请求就没有三次握手的开销,而且相较于HTTP1.0,HTTP1.1有了Pipeline,客户端可以像流水线一样发送自己的HTTP请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制
  • 网络知识基础:gzip和chunk是怎样优化网页传输的?
    目录 前言 一、文件传输的本质是什么? 二、http传输文件 三、http传输文件的方式 Content-length、chunk 四、chunk实现的介绍 前言 最近在看http原理的书籍,对http传输有了更深的理解。结合网上搜索的知识,总结下http的流传输。 一、文件传输的本质是什么? 文件是什么? 文件就是磁盘上的一段空间,文件的内容就是一串2进制数字(1或者0)。 文件传输,就是把这串数字通过http协议传过去。 服务器端,接到这段数据之后,按照协议规定的格式,把这串数字取出来,然后创建一个空文件(分配一段空间),然后把这段数字写进去,就成了一个跟上传文件完全一致的新文件。 二、http传输文件 首先http对于传输文件,通过文件头会又协议的约定,来告诉服务器,我所传输的是什么内容,文件名是什么,使用什么编码,等等内容。我在望山找了一个传输文件的http表单,表单里详细描述了传输文件的信息和内容。 然后,server接受到http传输的内容,根据请求头的信息,如怎么解码,文件名是什么,文件详细信息等。使用这些信息,将传来的内容进行解码、附加信息等,然后encode成磁盘能识别的串,存储在磁盘的空间中。 当我们从磁盘相应空间里取这段串时,经过解码,就是我们看到的文件和文件内容。 上面图片传输文件的流程如下: 读取 http body 部分根据 boundary
  • 为什么 IIS 不支持分块传输编码?(Why doesn't IIS support chunked transfer encoding?)
    问题 我正在与 IIS Web 服务器建立 HTTP 连接,并发送带有使用 Transfer-Encoding: chunked 编码的数据的 POST 请求。 当我这样做时,IIS 只是关闭连接,没有错误消息或状态代码。 根据 HTTP 1.1 规范, 所有 HTTP/1.1 应用程序必须能够接收和解码“分块”传输编码 所以我不明白为什么它 (a) 不处理该编码和 (b) 它不发回状态代码。 如果我更改请求以发送 Content-Length 而不是 Transfer-Encoding,则查询成功,但这并不总是可能的。 当我对 Apache 尝试同样的事情时,我得到“需要 411 长度”状态和一条消息“禁止分块传输编码”。 为什么这些服务器不支持这种编码? 回答1 我的理解是分块编码只能用于 HTTP 响应。 分块的请求主体具有与 1.0 服务器不兼容的特性,并且在任何情况下,用户代理都无法知道服务器是 1.0 服务器,直到它已经发送了请求。 但我同意文档中不清楚。 回答2 看看你的客户。 IIS 和 Apache 都支持使用分块传输编码的 POST 请求。 您可以使用 curl 实用程序验证这一点: curl <upload-url> --form "upfile=@<local_file>" --header "Transfer-Encoding: chunked" 使用
  • 响应以分块传输编码发送,并指示已发送某些数据后发生错误(Response sent in chunked transfer encoding and indicating errors happening after some data has already been sent)
    问题 我正在以分块传输编码格式向客户端发送大量数据。 我应该如何处理在编写响应期间中途发生的任何错误? 我想知道是否有关于此的任何HTTP Spec建议做法,以便客户端知道响应确实不是成功的,但是服务器遇到了问题。 回答1 一旦开始向客户端发送HTTP标头,就无法发送其他任何内容。 您必须完成要发送的响应的发送,即分块的数据和关联的标头。 如果在此过程中发生错误,则无法将错误报告给客户端。 您所能做的就是关闭连接。 客户端要么没有接收到所有标头,要么在响应结束时未接收到终止的0长度块。 无论哪种方式,客户端都可以知道服务器在发送过程中遇到了错误。 回答2 块状响应可以使用具有某些完整性检查或后处理状态的尾部标头。 这可能比接受的答案中所述的关闭连接更好,因为您可能会收到自定义错误消息。 但是,只有同时控制服务器和客户端,您才能从中受益。