V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
httpbin - 协议调试工具
httpstatuses - 协议状态码查询
httpie - cURL-like tool for humans
Fiddler
mason961125
V2EX  ›  HTTP

如何判断使用 keep-alive 的 HTTP 连接传输数据已经完成?

  •  
  •   mason961125 · 2015-08-02 22:35:11 +08:00 · 5106 次点击
    这是一个创建于 3401 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正在做一个HTTP代理,然而现在大部分的HTTP都使用了keep-alive,也就导致连接是一直开启并不close。然而我应该如何判断数据已经传输完成呢?
    目前我是用了一个checker来对每个连接进行timeout检验,超过规定的时间就认定传输已完成。
    所以,有更好的方法么?

    12 条回复    2015-08-03 13:55:50 +08:00
    wkdhf233
        1
    wkdhf233  
       2015-08-02 22:40:35 +08:00
    HTTP协议不是有结束界定的吗
    GET的话俩回车,POST之类的到达Content-Length。。
    zado
        2
    zado  
       2015-08-02 22:47:28 +08:00
    看那个Content-Length,这个数值加上http头大小就是全部数据的大小了。我也是定时检测,然后超过一定时间的就断开。
    imn1
        3
    imn1  
       2015-08-02 22:50:18 +08:00
    @wkdhf233
    NO
    socket 没断开的话,keep-alive 期内可以多次请求
    我写过一个爬虫就是用一次connect连续多次获取,定时断开
    不过对http1.0没用,网站那边需要至少1.1
    mason961125
        4
    mason961125  
    OP
       2015-08-02 22:53:32 +08:00
    @zado 虽然是个HTTP代理,但是遇到HTTPS的请求也是可以代理的。但是如果是HTTPS请求的话,是没办法知道请求头的吧(我记不太清楚了,错了求指正
    mason961125
        5
    mason961125  
    OP
       2015-08-02 22:54:28 +08:00
    @imn1 但是我又怕如果是看YouTube那种的长连接,在连接时间里数据基本一直在传输的,就无解了。
    wkdhf233
        6
    wkdhf233  
       2015-08-02 23:27:03 +08:00
    @imn1 同个socket多次请求,单次的结束界定你也得按协议规定来啊,你还能把俩GET挤到一起发出去?
    长连接是socket层面的东西,HTTP协议层面除了个keep-alive之外没啥变化的
    imn1
        7
    imn1  
       2015-08-02 23:28:43 +08:00
    没做过proxy,不过个人觉得杀掉 http 就可以了
    ssl 网站那边出于安全性和服务器性能,会有检查断开的机制
    定时检查连接数量,把时间较长和“不合理”的长连接强制断开就行了
    imn1
        8
    imn1  
       2015-08-02 23:39:43 +08:00
    @wkdhf233
    不是同时,是依次
    你可以自己写一个测试一下,根据字节或结束符判断传输完毕,保存或处理,不发送close,然后send另一个http请求,会有新的返回的
    反正我写过,较好的服务器连续请求5个不同url(当然服务器是同一个)成功,很多时候第6个请求失败(有些服务器线路不好的2~3个就不行了),但我的 socket 知识水平有限,异常处理得不好,所以没能继续写
    wkdhf233
        9
    wkdhf233  
       2015-08-03 00:15:24 +08:00
    @imn1 =_=长连接的程序我写过,因为PHP不好多线程所以一次把40+个请求送出去再慢慢处理返回,复用长连接本来也是十分常见的做法。

    我说的是,socket保持和HTTP协议的结束判断没有关系。socket只是承载传输,协议才是描述请求。要判断一个HTTP请求是否结束,只用根据协议的分割划分来就行。
    请求和请求间按照协议规定划分,而要是某个请求里没有keep-alive了,说明这个socket不用保持了。
    楼主担忧一个长连接照协议保持着但实际上没有作用了是多余的,不用了掐掉这是连接方的责任,还保持着就说明它还有可能传东西。

    代理方要做的只是统一设置一个超时时间,超过时间未活动(注意是未活动,每个带keep-alive的请求都应该清零计数器)的连接都掐掉就行了。
    zado
        10
    zado  
       2015-08-03 00:25:07 +08:00
    https 应该是没办法知道请求头的,所以应该也没有办法做代理吧,除非就是做成路由器那样的直接转发数据,那样就只能是在数据经过的时候记录一下时间,超过多长时间没有数据经过了就断开。
    loggerhead
        11
    loggerhead  
       2015-08-03 00:38:35 +08:00 via iPhone   ❤️ 1
    http 0.9或1.0 每次请求完成都会直接断开连接,并视为数据传完。
    1.1如果没有connection: close就会被认为是keep-live。如果服务器主动断开连接,需要在响应报文中设置connection: close,否则tcp连接处于半关闭,客户端发的数据服务器照样接收,但是不进行任何处理。
    不知道楼主是想问 如何判断还有没有请求,还是如何判断请求有没有传完?
    前者没法判断,后者得分析报文。
    julyclyde
        12
    julyclyde  
       2015-08-03 13:55:50 +08:00   ❤️ 1
    content-length或者chunked的尾0报 代表一个HTTP body的结束
    如果是没有body的,header行后面多加一个回车就算完
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1866 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 16:23 · PVG 00:23 · LAX 08:23 · JFK 11:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.