美文网首页
前端知识汇总(网络篇)

前端知识汇总(网络篇)

作者: cenkai88 | 来源:发表于2017-03-13 18:25 被阅读101次
  1. https 4次握手
  • c端请求,s端响应并提供证书(包括公钥、证书信息、颁发机构、过期时间等,s端私钥加密生成);
  • c端校验接收数据(主要是校验公钥确实是s端发的,见数字证书部分)后,生成pre-master-secret并使用s端发过来的公钥加密;
  • s端接收到后使用私钥解密,并最终通过某种算法生成master-secret;
  • 后续的通信中s和c端均使用这个master-secret生成的密钥。
    (其中两个secret是为了提高随机性,减少随机数被猜出的风险)
  1. 数字证书发布过程
  • 服务器生成一对密钥,私钥自己留着,公钥交给数字证书认证机构(CA) 。
  • CA进行审核,并用自己的私钥对服务器的公钥进行签名。
  • 客户端访问服务器时,从CA获取证书(包括服务器端公钥),用CA的公钥对签名的证书进行验证,一致则说明该服务器公钥确实是CA颁发的。
  1. https涉及的加密算法
  • 非对称加密(非对称加密算法用于握手过程中的加密生成的密码)
    RSA,DSA/DSS
  • 对称加密(对真正传输的数据进行加密):AES,RC4,3DES
  • HASH(用于验证数据的完整性,是否被篡改等):MD5,SHA1,SHA256
    非对称加密生成密码是整个加密过程的关键,非对称加密会生成公钥和私钥,公钥负责数据加密,可以随意传输。私钥负责解密。
  1. https如何优化
  • http使用TCP 三次握手建立连接,客户端和服务器需要交换3个包,https除了 TCP 的三个包,还要加上 SSL握手需要的9个包,所以一共是12个包。
  • https的开销主要是SSL部分(尤其是session建立阶段)。主要是网络延时和SSL本身加解密的开销(服务器根据客户端的信息确定是否需要生成新的主密钥;服务器回复该主密钥,并返回给客户端一个用主密钥认证的信息;服务器向客户端请求数字签名和公开密钥)。
  • 可以通过负载均衡的SSL termination proxy来优化,Web 服务放在SSL termination proxy之后。SSL termination proxy可以是基于硬件的,譬如F5;也可以软件的,如Nginx(维基百科用的)。
  • 另外也可以通过SSL session或SSL ticket复用来优化。session ID就是每一次对话都有一个编号(session ID)。只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的"对话密钥",但session ID 往往只保留在一台服务器上;而session ticket类似,但是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到 session ticket 以后,解密后就不必重新生成对话密钥了,支持负载均衡。
  • (Heartbleed就是RFC 在2012年提出了 RFC6520 TLS 的心跳扩展用于优化SSL所引起的漏洞。原本希望通过在客户端和服务器之间来回发送心跳的请求和应答,保活 TLS session,减少重建 TLS的session的性能开销,但未对心跳请求进行长度检查,导致客户端可以读服务器内存的数据。)
  1. http2特性
  • http的语义、头部、状态码、方法等不受影响
  • 服务器端推送消息
  • 传输二进制帧而非文本(乱序发帧并收到后重组)
  • 仅在一个TCP连接中并行处理(通过请求优先级控制)
  • 压缩头部信息减小开销
  • 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送
  1. 从输入url到渲染的整个过程
  • 客户端DNS寻址(浏览器DNS缓存、操作系统DNS缓存、本地域名服务器、向根域名服务器发送迭代请求)获得目标IP(有可能是CDN的IP)。
  • TCP或UDP连接建立。
  • 数据经过路由器到运营商网络,经过层层转发到达服务器。
  • 数据经过负载均衡(F5,LVS,反向代理)
  • 数据到达web server,经过后端业务逻辑
  • 如果采用SSR(服务器端渲染),则后端调用数据(数据库等)生成应用代码,如果是前后端分离架构,则数据和网页文件分别返回。
  • 数据通过网络回到客户端(内网NAT穿透)
  • 数据到达浏览器,如有gzip压缩先解压,开始编码(这里要注意是utf-8还是gbk)
  • html被解析(DOM树、CSSDOM树、呈现树等,见上面问题),加载外部资源,文字、图片渲染至屏幕。
  1. TCP三次握手,四次挥手过程
  • 三次握手


    三次握手
  • 四次挥手


    四次挥手
  1. CDN加速原理
  • 用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有DNS缓存,则向根域名服务器发起请求。
  • 根域名服务器设置了CNAME,指向了www.cdn.com,即CDN网络中的智能DNS负载均衡系统。
  • 智能DNS负载均衡系统解析域名,把对用户响应速度最快的IP节点返回给用户。
  • 用户向该IP节点(CDN服务器)发出请求。
  • 由于是第一次访问,CDN服务器会向原web站点请求,并缓存内容。
  • 请求结果发给用户。
  1. 静态资源优化
  • 配置超长时间的本地缓存(cache-control/expires) —— 节省带宽,提高性能
  • 采用hash值作为缓存更新依据 —— 精确的缓存控制
  • 静态资源CDN部署 —— 优化网络请求
  • 更新资源发布路径实现非覆盖式发布 —— 平滑升级
  1. 为何很多网站静态资源会使用独立的域名
  • 静态资源的http请求中不会携带无用的cookie。
  • 动静分离更有利于CDN。
  • http对同一个域名的同时下载线程数是有限制的,只要是为了优化下载速度,防止一个域名下太多下载线程,每个浏览器的限制不同。
  • 方便复用,放在另一个服务器上,可以方便全局内其他产品的使用,比如说taobao.com的js tmall也可以用,且客户端可缓存。
  1. 跨域解决
  • JSONP:仅支持get方法。原理是通过标签的src属性引用的文件可以跨域,那么传回一个脚本,将数据包在脚本中回调函数里并动态执行就可以拿到函数中的数据。
  • CORS:后端配置Access-Control-Allow-Origin(IE10+)。注意包括简单请求和复杂请求。
  • 代理:正向反向都可(nginx)
  1. CORS的简单请求和复杂请求
    方法为HEAD,GET,POST之一,且headers只包括Accept, Accept-Language, Content-Language, Last-Event-ID, Content-Type(值为application/x-www-form-urlencoded, multipart/form-data, text/plain之一)的请求为简单请求。
  • 简单请求浏览器直接发出,只添加一个origin头,服务器若允许该origin,则在响应头加上Access-Control-Allow-Origin: origin的值表示允许跨域。
    Access-Control-Allow-Credentials控制服务器是否接受Cookies,如果不为true但是传了Cookies,则前端会报异常(注意,如果接受Cookies则origin的值不能为星号)。
    Access-Control-Expose-Headers用来控制前端可以拿哪些响应头的header。
  • 复杂请求浏览器会先发一个OPTION方法的preflight请求。预检请求中Access-Control-Request-Method用来标志此次复杂请求的方法,Access-Control-Request-Headers表明复杂请求额外发送的header字段。服务器检查origin及method、header后,如果接受则类似简单请求发送响应,仅多一个Access-Control-Max-Age来标志预检的有效期。
  1. 自己写一个jsonp的实现
var JSONP = {
    now: function() { // 获取当前时间戳
        return (new Date()).getTime();
    },
    rand: function() { // 获取随机数
        return Math.random().toString().substr(2);
    },
    removeElem: function(elem) {
        var parent = elem.parentNode;
        if(parent && parent.nodeType !== 11) {
            parent.removeChild(elem);
        }
    },
    parseData: function(data) {  // url组装
        var ret = "";
        if(typeof data === "string") {
            ret = data;
        }else if(typeof data === "object") {
            for(var key in data) {
                ret += "&" + key + "=" + encodeURIComponent(data[key]);
            }
        }
        ret += "&_time=" + this.now();// 加个时间戳,防止缓存
        ret = ret.substr(1);
        return ret;
    },
    getJSON: function(url, data, func) {  // 函数名称
        var name;
        url = url + (url.indexOf("?") === -1 ? "?" : "&") + this.parseData(data); // 拼装url
        var match = /callback=(\w+)/.exec(url); // 检测callback的函数名是否已经定义
        if(match && match[1]) {
            name = match[1];
        } else {
            // 如果未定义函数名的话随机成一个函数名
            // 随机生成的函数名通过时间戳拼16位随机数的方式,重名的概率基本为0
            // 如:jsonp_1355750852040_8260732076596469
            name = "jsonp_" + this.now() + '_' + this.rand();
            url = url.replace("callback=?", "callback="+name);// 把callback中的?替换成函数名
            url = url.replace("callback=%3F", "callback="+name);// 处理?被encode的情况
        }  
        var script = document.createElement("script"); // 创建一个script元素
        script.type = "text/javascript";
        script.src = url; // 设置要远程的url
        script.id = "id_" + name;   // 设置id,为了后面可以删除这个元素

        // 把传进来的函数重新组装,并把它设置为全局函数,远程就是调用这个函数
        window[name] = function(json) {
            window[name] = undefined; // 执行这个函数后,要销毁这个函数
            var elem = document.getElementById("id_" + name); // 获取这个script的元素
            JSONP.removeElem(elem);  // 删除head里面插入的script,这三步都是为了不影响污染整个DOM啊
            func(json);  // 执行传入的的函数
        };  
        var head = document.getElementsByTagName("head");  // 在head里面插入script元素
        if(head && head[0]) {
            head[0].appendChild(script);
        }
    }
};
//调用的方法跟jQuery基本一样。如:
var data = {
            from: "北京",
            count: 27,
            output: "json",
            callback: "?"
        }
JSONP.getJSON("http://api.qunar.com/cdnWebservices.jcp", data, function(json) {console.log(json)});
  1. 原生ajax
<script>
 // 1.获得ajax
 if (window.XMLHttpRequest) { //查看当前浏览器XMLHttpRequest是否是全局变量
     var oAjax = new XMLHttpResquest();
 } else {
     var oAjax = new ActiveXObject('Microsoft.XMLHTTP'); //IE6,传入微软参数
 }

 // 2.打开地址
 switch (json.type.toLowerCase()) {
     case 'get':
         oAjax.open('GET', json.url + '?' + jsonToURL(json.data), true); // 提交方式(大写),url,是否异步
// 3.发送GET数据
         oAjax.send();
         break;
     case 'post':
         oAjax.open('POST', json.url, true);
         oAjax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
         oAjax.send(jsonToURL(json.data)); 
// 3.发送POST数据
        break;
 }

 // 4.接收数据
 oAjax.onreadystatechange = function() { //监控状态
     if (oAjax.readyState == 4) {
         json.complete && json.complete();
         if (oAjax.status >= 200 && oAjax.status < 300 ||
             oAjax.status == 304) {
             json.success && json.success(oAjax.responseText); //执行成功的回调函数, responseText为响应内容
         } else {
             json.error && json.error(oAjax.status); //执行失败的回调函数
         }
     }
 };
</script>

相关文章

网友评论

      本文标题:前端知识汇总(网络篇)

      本文链接:https://www.haomeiwen.com/subject/nddqnttx.html