IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    HttpURLConnection在底层是否复用socket的简单验证方式

    hongjiang发表于 2016-07-08 20:53:47
    love 0

    关于JDK自身的HttpURLConnection在底层是否复用socket的测试方式,可以快速用repl和lsof来检测:

    // 本地启动一个 http server,它返回十几个字符
     ➜  curl "http://localhost:8080/sleep?time=1000"
    {"code":"ok"}
    
    // 在repl下连续请求这个url 若干次
    scala> val is = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.getInputStream; for(i <- 1 to 15) is.read; is.close
    is: java.io.InputStream = sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@1ba9117e
    
    scala> val is = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.getInputStream; for(i <- 1 to 15) is.read; is.close
    is: java.io.InputStream = sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@a82c5f1
    

    与此同时在另一个终端用lsof查看socket,每秒刷新一次,可看到客户端socket是同一个

     ➜  /usr/sbin/lsof -Pan -iTCP -r 1 -p 43280
    =======
    =======
    COMMAND   PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    java    43280 hongjiang   47u  IPv6 0x43acdfd2ea5b0c01      0t0  TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
    =======
    COMMAND   PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    java    43280 hongjiang   47u  IPv6 0x43acdfd2ea5b0c01      0t0  TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
    =======
    COMMAND   PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    java    43280 hongjiang   47u  IPv6 0x43acdfd2ea5b0c01      0t0  TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
    =======
    COMMAND   PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    java    43280 hongjiang   47u  IPv6 0x43acdfd2ea5b0c01      0t0  TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)  
    

    这个话题是由URLConnection在关闭的时候应该调用close还是disConnect所引起的,关于jdk里keep-alive相关的一些参数不展开了。

    验证disconnect方法:

    // 执行若干次
    scala> val conn = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.asInstanceOf[java.net.HttpURLConnection]; val is=conn.getInputStream; for(i <- 1 to 15) is.read; conn.disconnect
    

    这时没法用lsof观察了,它最小刷新单位是1秒,因为每次连接立即关闭导致没机会看到,得用tcpdump来观察

     ➜  sudo tcpdump -i lo0  -s 1024 -l -A  port 8080
    
     ^[[A04:59:57.066577 IP localhost.57355 > localhost.http-alt: Flags [S]
     ...
     -`=.-`=.GET /sleep?time=100 HTTP/1.1
    User-Agent: Java/1.8.0_51
    Host: localhost:8080
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    
    ...
    
    05:00:05.407691 IP localhost.57356 > localhost.http-alt: Flags [P.], seq 1:168, ack 1, win 12759, options [nop,nop,TS val 761290281 ecr 761290281], length 167: HTTP: GET /sleep?time=100 HTTP/1.1
    E...LF@.@.........................1........
    -`^)-`^)GET /sleep?time=100 HTTP/1.1
    User-Agent: Java/1.8.0_51
    Host: localhost:8080
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive 
    
    ... 
    
    05:00:07.045830 IP localhost.57357 > localhost.http-alt: Flags [P.], seq 1:168, ack 1, win 12759, options [nop,nop,TS val 761291915 ecr 761291915], length 167: HTTP: GET /sleep?time=100 HTTP/1.1
    E.....@.@................l.;.\.,..1........
    -`d.-`d.GET /sleep?time=100 HTTP/1.1
    User-Agent: Java/1.8.0_51
    Host: localhost:8080
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    

    看到三次连接每次客户端socket端口都变了。



沪ICP备19023445号-2号
友情链接