http2 公约分分快三计划

作者:分分快三计划

浏览器支持

主流浏览器都只支持 HTTP/2 Over TLS

HTTP/2 源自 SPDY/2

SPDY 系列协议由谷歌开发,于 2009 年公开。它的设计目标是降低 50% 的页面加载时间。当下很多著名的互联网公司都在自己的网站或 APP 中采用了 SPDY 系列协议(当前最新版本是 SPDY/3.1),因为它对性能的提升是显而易见的。主流的浏览器(谷歌、火狐、Opera)也都早已经支持 SPDY,它已经成为了工业标准,HTTP Working-Group 最终决定以 SPDY/2 为基础,开发 HTTP/2。HTTP/2标准于2015年5月以RFC 7540正式发表。

但是,HTTP/2 跟 SPDY 仍有不同的地方,主要是以下两点:

HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
HTTP/2 消息头的压缩算法采用 HPACK ,而非 SPDY 采用的 DEFLATE(感谢网友 逸风之狐指正)

协议文档请见:rfc7540:HTTP2

浏览器和web服务支持情况

http2 支持清单

node中启用http2

node中可以用spdy模块来启动应用,spdy的api,与https是一致的且主流浏览器只支持HTTP/2 Over TLS,需要配置 私钥和证书,本地自签名服务器配置可参考引用6,7

JavaScript

const express = require('express'); const fs = require('fs'); const http2 = require('spdy'); const path = require('path'); const options = { key: fs.readFileSync('./keys/privatekey.pem'), cert: fs.readFileSync('./keys/certificate.pem') }; const app = new express(); http2 .createServer(options, app) .listen(8080, ()=>{ console.log(`Server is listening on . You can open the URL in the browser.`) } ) app.use("/",(req,res)=>{ res.send("hello http2!"); })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const express = require('express');
const fs =  require('fs');
const http2 = require('spdy');
const path = require('path');
const options = {
    key: fs.readFileSync('./keys/privatekey.pem'),
    cert: fs.readFileSync('./keys/certificate.pem')
};
const app = new express();
http2
  .createServer(options, app)
  .listen(8080, ()=>{
    console.log(`Server is listening on https://localhost:8080.
     You can open the URL in the browser.`)
  }
)
app.use("/",(req,res)=>{
    
  res.send("hello http2!");
})

如上,对于已存在的项目只要修改几行代码就可以使用http2.0了。

请求头和响应头:

说明:新版的Chrome,对不安全的证书(如本地的自签名服务)会降级到http1.1,firefox不会出现此问题。

启动server push

JavaScript

app.get("/",(req,res)=>{ var stream = res.push('/app.js', { //服务器推送 status: 200, // optional method: 'GET', // optional request: { accept: '*/*' }, response: { 'content-type': 'application/javascript' } }) stream.on('error', function() { }) stream.end('console.log("http2 push stream, by Lucien ");') res.send(`hello http2! <script src="/app.js"></script>`);//express 并没有host static ,这个app.js 来自push })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
app.get("/",(req,res)=>{
    var stream = res.push('/app.js', {   //服务器推送
    status: 200, // optional
    method: 'GET', // optional
    request: {
      accept: '*/*'
    },
    response: {
      'content-type': 'application/javascript'
    }
  })
  stream.on('error', function() {
  })
  stream.end('console.log("http2 push stream, by Lucien ");')
 
  res.send(`hello http2!
    <script src="/app.js"></script>`);//express 并没有host static ,这个app.js 来自push
})

源码在github

响应

3. 数据流

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

相关资料

  • http2 讲解

  • http2 home

  • http2 专题

  • 【协议分析】HTTP2优势分析

5. 服务器推送

服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。

那么存在一个问题,如果客户端设置了缓存怎么办。有三种方式(来自社区)

  • 客户端可以通过设置SETTINGS_ENABLE_PUSH为0值通知服务器端禁用推送
  • 发现缓存后,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。
  • cache-digest(提案)

    rfc7540: HTTP2 Server Push

    #### 6. 流优先级

    HTTP2允许浏览器指定资源的优先级。

    rfc7540: Stream Priority

浏览器支持

分分快三计划 1

主流浏览器都只支持 HTTP/2 Over TLS

配置https

HTTP/2 协议本身并没有要求必须基于 TLS 部署,但是 Chrome 和 Firefox 均表示只支持 HTTP/2 Over TLS。一方面更安全,希望保护以及尊重用户的隐私,一方面利用 TLS 的加密机制可以更好地穿透网络中间节点。需要先配置https。

# 创建一个私钥文件:

openssl genrsa -des3 -out server.key 1024

openssl req -new -key server.key -out server.csr

openssl rsa -in server.key -out server_nopass.key

# 结合密钥和证书生成请求,创建一个自签署的CA证书

openssl req -new -x509 -days 3650 -key server_nopass.key -out server.crt

配置nginx

server
{
    listen 443 ssl http2;
    server_name  www.kailian.com;
    index index.php index.html;
    root  /data/web/www;
    ssl on;
    ssl_certificate /usr/local/etc/nginx/server.crt;
    ssl_certificate_key /usr/local/etc/nginx/server_nopass.key;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH ECDSA AESGCM EECDH aRSA AESGCM EECDH ECDSA SHA384 EECDH ECDSA SHA256 EECDH aRSA SHA384 EECDH aRSA SHA256 EECDH aRSA RC4 EECDH EDH aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    keepalive_timeout 70;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m; 

    charset utf-8;
    location ~ .*.php$
    {
        include fastcgi.conf;
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
    }

}

一分钟预览 HTTP2 特性和抓包分析

2016/09/26 · JavaScript · HTTP/2

原文出处: 段隆贤   

1. 二进制协议

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式

分分快三计划 2

由上图可以看到HTTP2在原来的应用层和HTTP层添加了一层二进制传输。

二进制协议的一个好处是,可以定义额外的帧。

HTTP/2 定义了近十种帧(详情可分析抓包文件),为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
RFC7540:Frame Definitions
分分快三计划 3
协议中定义的帧

安装部署

从 Nginx 1.9.5 开始,http_v2_module 已经替换了 ngx_http_spdy_module,安装版本用1.10.1

nginx

./configure --with-http_v2_module

mac

brew options nginx
brew install nginx --with-http2

最后

最后,HTTP2有更高的传输速度,更少的资源占用,可以去除各种性能优化tricks(如css sprite,inline-image.)
转向WEB开发的美好未来T.T

最后

最后,HTTP2有更高的传输速度,更少的资源占用,可以去除各种性能优化tricks(如css sprite,inline-image.)
转向WEB开发的美好未来T.T

http2 协议

HTTP/2 源自 SPDY/2,正式版http2规格标准叫做RFC 7540,发布于2015年5月15日。

  • RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)

  • RFC 7541 - HPACK: Header Compression for HTTP/2

  • fex-team翻译的 htt2 中英文对照.md)

HTTP/2 跟 SPDY 仍有不同的地方,主要是以下两点:

  1. HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS

  2. HTTP/2 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DELEFT

背景

近年来,http网络请求量日益添加,以下是httparchive统计,从2012-11-01到2016-09-01的请求数量和传输大小的趋势图:

分分快三计划 4

 

当前大部份客户端&服务端架构的应用程序,都是用http/1.1连接的,现代浏览器与单个域最大连接数,都在4-6个左右,由上图Total Requests数据,如果不用CDN分流,平均有20个左右的串行请求。
HTTP2 是1999年发布http1.1后的一次重大的改进,在协议层面改善了以上问题,减少资源占用,来,直接感受一下差异:

HTTP/2 is the future of the Web, and it is here!
这是 Akamai 公司建立的一个官方的演示,用以说明 HTTP/2 相比于之前的 HTTP/1.1 在性能上的大幅度提升。 同时请求 379 张图片,从Load time 的对比可以看出 HTTP/2 在速度上的优势。

分分快三计划 5

 

本文所有源码和抓包文件在github

HTTP2特性概览

http2 特点

http2 性能,http2 demo

  • HTTP/2's binary framing layer

  • Streams, messages, and frames

  • Request and response multiplexing

  • Stream prioritization

  • One connection per origin

  • Flow control

  • Server push

  • Header compression

(1)二进制

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。二进制协议解析起来更高效。

(2)二进制格式

HTTP/1 的请求和响应报文,都是由起始行、首部和实体正文(可选)组成,各部分之间以文本换行符分隔。

HTTP/2 将请求和响应数据分割为更小的帧,并对它们采用二进制编码。

帧(Frame):HTTP/2 数据通信的最小单位。

消息(Message):指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成

流(Stream):存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。

HTTP/2 中,同域名下所有通信都在单个连接上完成,这个连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

Frame 是 HTTP/2 二进制格式的基础,Frame 的基本格式如下

 ----------------------------------------------- 
|                 Length (24)                   |
 --------------- --------------- --------------- 
|   Type (8)    |   Flags (8)   |
 - ------------- --------------- ------------------------------- 
|R|                 Stream Identifier (31)                      |
 = ============================================================= 
|                   Frame Payload (0...)                      ...
 --------------------------------------------------------------- 

字段含义可查看协议

分分快三计划 6

http2.png

(3)多路复用

HTTP/1.X 存在线端阻塞(head-of-line blocking)的问题。HTTP/1.1 试过用流水线(pipelining)来解决这个问题, 但是效果并不理想(数据量较大或者速度较慢的响应, 会阻碍排在他后面的请求)。HTTP 管道技术无法大规模使用。

多路复用,代替原来的序列和阻塞机制。就是所有的请求都是通过一个 TCP连接并发完成。流支持优先级流量控制

HTTP/2 的多路复用特性,使得可以在一个连接上同时打开多个流,双向传输数据。每次请求/响应使用不同的 Stream ID。通过 Stream ID 标识,所有的请求和响应都同时跑在一条 TCP 链接上。 当流并发时,就会涉及到流的优先级和依赖。优先级高的流会被优先发送。图片请求的优先级要低于 CSS 和 SCRIPT,这个设计可以确保重要的东西可以被优先加载完。http2上面每个流都拥有自己的公示的流量窗口,它可以限制另一端发送数据。

(4)头压缩

HTTP 1.1请求的大小变得越来越大,有时甚至会大于TCP窗口的初始大小,这会严重拖累发送请求的速度。因为它们需要等待带着ACK的响应回来以后,才能继续被发送。

HTTP/2 对消息头采用 HPACK (专为http2头部设计的压缩格式)进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。

(5)服务端推送

服务端可以在发送页面 HTML 时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。

服务端可以主动推送,客户端也有权利选择接收与否。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。

抓包分析

可以用chrome 内部自带的工具(chrome://net-internals/)查看http2流量,但这个包信息量比较少,结构不如我们熟悉的Fiddler查看http2流量,但这个包信息量比较少,结构不如我们熟悉的Fiddler) or Wireshark清晰。

Fiddler是直接作为中间代理,可以作为客户端直接与服务端通讯,可以像浏览器那样直接解密https,直接看到https报文,
但是由于受限于.NET Framework暂不支持Http2.

用wireshark直接抓包 https:443端口的流量是这样的:

数据被加密了,协议细节完全看不到。
这里介绍了一种方法获取私钥解包。
抓包https包时要把代理关了,不然私钥不是同一个,wireshark不能解包(被这个坑了两小时T T)。

一个包内有多个不同的Steam ID

追踪解密后TCP流可以看到,由于多路复用,各个不同的请求交替传输不同的帧,所以流数据是乱的。但在同一帧内数据还是正常的。

node中启用http2

node中可以用spdy模块来启动应用,spdy的api,与https是一致的且主流浏览器只支持HTTP/2 Over TLS,需要配置 私钥和证书,本地自签名服务器配置可参考引用6,7

const express = require('express');
const fs =  require('fs');
const http2 = require('spdy');
const path = require('path');
const options = {
    key: fs.readFileSync('./keys/privatekey.pem'),
    cert: fs.readFileSync('./keys/certificate.pem')
};
const app = new express();
http2
  .createServer(options, app)
  .listen(8080, ()=>{
    console.log(`Server is listening on https://localhost:8080.
     You can open the URL in the browser.`)
  }
)
app.use("/",(req,res)=>{

  res.send("hello http2!");
})

如上,对于已存在的项目只要修改几行代码就可以使用http2.0了。

请求头和响应头:
分分快三计划 7

说明:新版的Chrome,对不安全的证书(如本地的自签名服务)会降级到http1.1,firefox不会出现此问题。

启动server push

app.get("/",(req,res)=>{
    var stream = res.push('/app.js', {   //服务器推送
    status: 200, // optional
    method: 'GET', // optional
    request: {
      accept: '*/*'
    },
    response: {
      'content-type': 'application/javascript'
    }
  })
  stream.on('error', function() {
  })
  stream.end('console.log("http2 push stream, by Lucien ");')

  res.send(`hello http2!
    <script src="/app.js"></script>`);//express 并没有host static ,这个app.js 来自push 
})

源码在github

响应

分分快三计划 8

分分快三计划 9

测试

chrome插件

ssllabs查看https配置是否够快

在 Chrome 地址栏输入chrome://net-internals/#http2,打开 Chrome 自带的 HTTP/2 查看工具,可查看 HTTP/2 帧信息

Wireshark抓包查看

2. 多路复用

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”(见TCP/IP详解卷一)。
每个 Frame Header 都有一个 Stream ID 就是被用于实现该特性。每次请求/响应使用不同的 Stream ID。就像同一个 TCP 链接上的数据包通过 IP: PORT 来区分出数据包去往哪里一样。

分分快三计划 10

rfc7540: HTTP2 Multiplexing中对Multiplexing的说明

Streams and Multiplexing A "stream" is an independent, bidirectional sequence of frames exchanged between the client and server within an HTTP/2 connection. Streams have several important characteristics: o A single HTTP/2 connection can contain multiple concurrently open streams, with either endpoint interleaving frames from multiple streams. o Streams can be established and used unilaterally or shared by either the client or server. o Streams can be closed by either endpoint. o The order in which frames are sent on a stream is significant. Recipients process frames in the order they are received. In particular, the order of HEADERS and DATA frames is semantically significant. o Streams are identified by an integer. Stream identifiers are assigned to streams by the endpoint initiating the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Streams and Multiplexing
 
   A "stream" is an independent, bidirectional sequence of frames
   exchanged between the client and server within an HTTP/2 connection.
   Streams have several important characteristics:
 
   o  A single HTTP/2 connection can contain multiple concurrently open
      streams, with either endpoint interleaving frames from multiple
      streams.
 
   o  Streams can be established and used unilaterally or shared by
      either the client or server.
 
   o  Streams can be closed by either endpoint.
 
   o  The order in which frames are sent on a stream is significant.
      Recipients process frames in the order they are received.  In
      particular, the order of HEADERS and DATA frames is semantically
      significant.
 
   o  Streams are identified by an integer.  Stream identifiers are
      assigned to streams by the endpoint initiating the stream.

参考资料

  1. Turn-on HTTP/2 today!
  2. Hypertext Transfer Protocol Version 2 (HTTP/2)
  3. npm spdy
  4. npm spdy push
  5. How to create a self-signed SSL Certificate
  6. HPACK: Header Compression for HTTP/2
  7. 用Node.js创建自签名的HTTPS服务器

HTTP/2 源自 SPDY/2

SPDY 系列协议由谷歌开发,于 2009 年公开。它的设计目标是降低 50% 的页面加载时间。当下很多著名的互联网公司都在自己的网站或 APP 中采用了 SPDY 系列协议(当前最新版本是 SPDY/3.1),因为它对性能的提升是显而易见的。主流的浏览器(谷歌、火狐、Opera)也都早已经支持 SPDY,它已经成为了工业标准,HTTP Working-Group 最终决定以 SPDY/2 为基础,开发 HTTP/2。HTTP/2标准于2015年5月以RFC 7540正式发表。

但是,HTTP/2 跟 SPDY 仍有不同的地方,主要是以下两点:

HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
HTTP/2 消息头的压缩算法采用 HPACK ,而非 SPDY 采用的 DEFLATE(感谢网友 逸风之狐指正)

协议文档请见:rfc7540:HTTP2

5. 服务器推送

服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。

那么存在一个问题,如果客户端设置了缓存怎么办。有三种方式(来自社区)

  • 客户端可以通过设置SETTINGS_ENABLE_PUSH为0值通知服务器端禁用推送
  • 发现缓存后,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。
  • cache-digest(提案)

    rfc7540: HTTP2 Server Push

    #### 6. 流优先级

    HTTP2允许浏览器指定资源的优先级。

    rfc7540: Stream Priority

4. 头信息压缩:

HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。
HTTP2对http头建立索引表,相同的头只发送hash table 的index, 同时还用了霍夫曼编码和传统的gzip压缩。

抓包分析

可以用chrome 内部自带的工具(chrome://net-internals/)查看http2流量,但这个包信息量比较少,结构不如我们熟悉的Fiddler查看http2流量,但这个包信息量比较少,结构不如我们熟悉的Fiddler) or Wireshark清晰。

Fiddler是直接作为中间代理,可以作为客户端直接与服务端通讯,可以像浏览器那样直接解密https,直接看到https报文,
但是由于受限于.NET Framework暂不支持Http2.

用wireshark直接抓包 https:443端口的流量是这样的:
分分快三计划 11

数据被加密了,协议细节完全看不到。
这里介绍了一种方法获取私钥解包。
抓包https包时要把代理关了,不然私钥不是同一个,wireshark不能解包(被这个坑了两小时T T)。

分分快三计划 12

分分快三计划 13

一个包内有多个不同的Steam ID

分分快三计划 14

追踪解密后TCP流可以看到,由于多路复用,各个不同的请求交替传输不同的帧,所以流数据是乱的。但在同一帧内数据还是正常的。

参考资料

  1. Turn-on HTTP/2 today!
  2. Hypertext Transfer Protocol Version 2 (HTTP/2)
  3. npm spdy
  4. npm spdy push
  5. How to create a self-signed SSL Certificate
  6. HPACK: Header Compression for HTTP/2
  7. 用Node.js创建自签名的HTTPS服务器

    1 赞 收藏 评论

分分快三计划 15

4. 头信息压缩:

HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。
HTTP2对http头建立索引表,相同的头只发送hash table 的index, 同时还用了霍夫曼编码和传统的gzip压缩。

HTTP2特性概览

背景

近年来,http网络请求量日益添加,以下是httparchive统计,从2012-11-01到2016-09-01的请求数量和传输大小的趋势图:

分分快三计划 16

当前大部份客户端&服务端架构的应用程序,都是用http/1.1连接的,现代浏览器与单个域最大连接数,都在4-6个左右,由上图Total Requests数据,如果不用CDN分流,平均有20个左右的串行请求。
HTTP2 是1999年发布http1.1后的一次重大的改进,在协议层面改善了以上问题,减少资源占用,来,直接感受一下差异:

http2 公约分分快三计划。HTTP/2 is the future of the Web, and it is here!
这是 Akamai 公司建立的一个官方的演示,用以说明 HTTP/2 相比于之前的 HTTP/1.1 在性能上的大幅度提升。 同时请求 379 张图片,从Load time 的对比可以看出 HTTP/2 在速度上的优势。

分分快三计划 17

本文所有源码和抓包文件在github

3. 数据流

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

2. 多路复用

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"(见TCP/IP详解卷一)。
每个 Frame Header 都有一个 Stream ID 就是被用于实现该特性。每次请求/响应使用不同的 Stream ID。就像同一个 TCP 链接上的数据包通过 IP: PORT 来区分出数据包去往哪里一样。
分分快三计划 18

rfc7540: HTTP2 Multiplexing中对Multiplexing的说明

Streams and Multiplexing

   A "stream" is an independent, bidirectional sequence of frames
   exchanged between the client and server within an HTTP/2 connection.
   Streams have several important characteristics:

   o  A single HTTP/2 connection can contain multiple concurrently open
      streams, with either endpoint interleaving frames from multiple
      streams.

   o  Streams can be established and used unilaterally or shared by
      either the client or server.

   o  Streams can be closed by either endpoint.

   o  The order in which frames are sent on a stream is significant.
      Recipients process frames in the order they are received.  In
      particular, the order of HEADERS and DATA frames is semantically
      significant.

   o  Streams are identified by an integer.  Stream identifiers are
      assigned to streams by the endpoint initiating the stream.

1. 二进制协议

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式

分分快三计划 19

 

由上图可以看到HTTP2在原来的应用层和HTTP层添加了一层二进制传输。

二进制协议的一个好处是,可以定义额外的帧。

HTTP/2 定义了近十种帧(详情可分析抓包文件),为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
RFC7540:Frame Definitions

分分快三计划 20

协议中定义的帧

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 JavaScript HTML5 计算机基础 HTTP