如何判断使用 keep-alive 的 HTTP 连接传输数据已经完成? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
httpbin - 协议调试工具
httpstatuses - 协议状态码查询
httpie - cURL-like tool for humans
Fiddler
mason961125
V2EX    HTTP

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

  •  
  •   mason961125 2015 年 8 月 2 日 5585 次点击
    这是一个创建于 3846 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    代理方要做的只是统一设置一个超时时间,超过时间未活动(注意是未活动,每个带keep-alive的请求都应该清零计数器)的连接都掐掉就行了。
    zado
        10
    zado  
       2015 年 8 月 3 日
    https 应该是没办法知道请求头的,所以应该也没有办法做代理吧,除非就是做成路由器那样的直接转发数据,那样就只能是在数据经过的时候记录一下时间,超过多长时间没有数据经过了就断开。
    loggerhead
        11
    loggerhead  
       2015 年 8 月 3 日 via iPhone   1
    http 0.9或1.0 每次请求完成都会直接断开连接,并视为数据传完。
    1.1如果没有connection: close就会被认为是keep-live。如果服务器主动断开连接,需要在响应报文中设置connection: close,否则tcp连接处于半关闭,客户端发的数据服务器照样接收,但是不进行任何处理。
    不知道楼主是想问 如何判断还有没有请求,还是如何判断请求有没有传完?
    前者没法判断,后者得分析报文。
    julyclyde
        12
    julyclyde  
       2015 年 8 月 3 日   1
    content-length或者chunked的尾0报 代表一个HTTP body的结束
    如果是没有body的,header行后面多加一个回车就算完
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2460 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 82ms UTC 13:07 PVG 21:07 LAX 05:07 JFK 08:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86