美文网首页
HTTP协议1.1

HTTP协议1.1

作者: Vivian_0430 | 来源:发表于2020-08-14 09:52 被阅读0次

    打开chrome的调试面板,切换到network面板,搞清楚该页上所有的显示项、菜单、弹窗等下级功能的含义

    1. 什么是TTFB?TTFB包含了哪些部分?

    Time to first byte,Timing里面的waiting,从http请求发送到服务器接收第一个字节的时间花费。

    包含了TCP连接时间,http请求发送时间和服务器接收到第一个字节的时间。

    1. network面板里看到一个请求,怎么判断这个请求真的发送到了服务器那里?

    根据状态码来看,502和504是没有发送到服务器,304从浏览器读取缓存。

    1. 一条请求变红了可能是因为哪些原因?

    4,5开头的状态码,插件阻拦,浏览器的一些约定和协议

    HTTP协议的特征:

    1. 两方通信
    2. 非对等的通信双方(server/client)
    3. 通信的基本单元(request和response)
    4. 请求与返回的对应关系

    请写出一个简单的http请求:(method放前面,协议放后面)

    初始行:method + path + 协议(GET /index.html HTTP/1.1\r\n HOST: www.maxtropy.com\r\n\r\n)

    注:CRLF

    1. 回车 = CR = \r
    2. 换行 = LF = \n

    HTTP基于TCP运行

    TCP:两河模型

    怎么知道一条请求已经结束了?答:\r\n

    怎么区分前一条请求和后一条请求?答:\r\n\r\n

    const str = "GET /index.html HTTP/1.1\r\nHost: www.maxtropy.com\r\n\r\nGET /main.js HTTP/1.1\r\nHost: www.maxtropy.com\r\n\r\n"
    function parseRequest(str) {
        const result = [];
        const arr = str.split('\r\n\r\n');
        arr.forEach(item => {
            const data = item.split('\r\n');
            result.push({
                requestLine: data[0],
                headers: data[1].split()
            })
        })
    }
    

    写出一个带有body的http POST请求:

    POST /index.html HTTP/1.1\r\n

    HOST: www.maxtropy.com\r\n

    Content-Length: 14\r\n\r\n

    body: {json}

    interface RequestObject {
        requestLine: string;
        headers: string[];
        body?: string;
    }
    class RequestProcessor {
        feed(rawData: string): void {
            
        }
        poll():RequestObject | undefined {
            return undefined;
        }
    }
    
    const str0 = 'POST /user/';
        const str1 = 'create HTTP/1.1\r\nHost: www.';
        const str2 = 'maxtropy.com\r\nqwee: Content-Length: 19\r\nContent';
        const str3 = '-Length: 19\r\n\r\n';
        const str4 = '{"name":"';
        const str5 = 'tom","\r\n"}POST';
        const str6 = ' /user/';
        const str7 = 'create HTTP/1.1\r\nHost: www.';
        const str8 = 'maxtropy.com\r\nContent';
        const str9 = '-Length: 21\r\n\r\n';
        const str10 = '{"name":"';
        const str11 = 'tom","\r\n\r\n"}';
    
        const test0 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length:15\r\n\r\n{'name': 'tom'}GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test1 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 17\r\n\r\nContent-Length=16GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test2 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 9\r\n\r\nGET HOST:GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test3 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 6\r\n\r\n\r\n\r\n\r\nGET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test4 = "GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\nPOST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 15\r\n\r\n{'name': 'tom'}";
        const test5 = "GET /main.js HTTP/1.1\r\nHost: www.test";
        const test6 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 6\r\n\r\n\r\ntestGET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test7 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 15\r\n\r\n{'name': 'tom'}GET /main.js HTTP";
        const test8 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 15\r\n\r\n{'name': 'tom'}GET /main.js HTTP/1.1\r\nHost: www.test.com";
        const test9 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 15\r\n\r\n{'name': 'tom'}GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\nGET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        const test10 = "POST /index.js HTTP/1.1\r\nHost: www.test.com\r\nContent-Length: 15\r\n\r\n{'name': GET GET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\nGET /main.js HTTP/1.1\r\nHost: www.test.com\r\n\r\n";
        let result = [];
        let newUrl = '';
        function feed(rawData){
            newUrl = newUrl + rawData;
            let requestUrl = '';
            let indexArr = [];
            let firstIndex = -1;
            for (let i = 0;i < newUrl.length;i++) {
                if(String(newUrl[i] + newUrl[i+1] + newUrl[i+2] + newUrl[i+3]) === '\r\n\r\n') {
                    requestUrl = newUrl.substring(0,i);
                    firstIndex = i;
                    break;
                }
            }
            for (let i = 0; i < requestUrl.length; i++) {
                if (String(requestUrl[i] + requestUrl[i + 1]) === '\r\n') {
                    indexArr.push(i)
                }
            }
            if (firstIndex !== -1) {
                if (requestUrl.toLocaleUpperCase().indexOf('CONTENT-LENGTH:') === -1) { // 不带body
                    result.push({
                        requestLine: requestUrl.substring(0, indexArr[0]),
                        headers: requestUrl.substring(indexArr[0]+2)
                    });
                    newUrl = newUrl.substring(requestUrl.length).trim();
                    feed('')
                } else {
                    const contentLength = Number(requestUrl.toLocaleUpperCase().trim().split('CONTENT-LENGTH:')[1]);
                    //---- body尚不完整的情况
                    if (newUrl.length >= requestUrl.length + contentLength + 4) {
                        result.push({
                            requestLine: requestUrl.substring(0, indexArr[0]),
                            headers: requestUrl.substring(indexArr[0] + 2, firstIndex).split('\r\n'),
                            body: newUrl.substr(firstIndex+4, contentLength)
                        });
                        newUrl = newUrl.substring(requestUrl.length + contentLength + 4);
                        feed('')
                    }
                }
            }
        }
        function poll() {
            if(result.length) {
                const first = result[0];
                result.shift();
                return first
            }else {
                return undefined;
            }
        }
        // feed(str0);
        // console.log(poll());
        // feed(str1);
        // console.log(poll());
        // feed(str2);
        // console.log(poll());
        // feed(str3);
        // console.log(poll());
        // feed(str4);
        // console.log(poll());
        // feed(str5);
        // console.log(poll());
        // feed(str6);
        // console.log(poll());
        // feed(str7);
        // console.log(poll());
        // feed(str8);
        // console.log(poll());
        // feed(str9);
        // console.log(poll());
        // feed(str10);
        // console.log(poll());
        // feed(str11);
        // console.log(poll());
        feed(test3);
        console.log(poll(),poll(),poll());
    

    分别写出一个带body和不带body的response:(协议放在前面)

    不带body

    HTTP/1.1 200 OK
    max-age: 0
    

    带body

    HTTP/1.1 200 OK 
    max-age: 0 
    Content-Length: 14
    {json}
    

    请求及相应结构:

    start-line + *(header-field CRLF) + CRLF + [message-body]

    1. HTTP为什么不能是多方通信?

    request和response不能一一对应

    1. 怎么区分client和server?

    通过发送的信息的结构

    1. server怎么向client主动发送数据?

    webSocket,SSE,HTTP是不能实现的,因为client会把请求当响应处理报错

    https://tools.ietf.org/html/rfc2119

    延伸:

    1. 了解HTTP chunked编码及其使用场景

    服务器返回的消息的长度,像前台给后台的Content-Length一样;transfer-coding的阈值为chunked时表示将用chunked编码传输内容;

    使用场景:前台下载大文件

    1. 了解WebSocket的协议细节,与HTTP协议的不同之处

    WebSocket 是基于TCP/IP协议,独立于HTTP协议的通信协议;双向通讯,有状态,客户端一(多)个与服务端一(多)双向实时响应(客户端 ⇄ 服务端);持久化协议;

    GET /webfin/websocket/ HTTP/1.1
    Host: localhost
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
    Origin: http://localhost:8080
    Sec-WebSocket-Version: 13
    
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
    
    1. HTTP/1.1队头阻塞的问题

    由于http一发一收的应答机制(请求-应答模型),如果队首的请求处理太慢就会阻塞后面的进程。

    解决办法:并发连接,客户端对一个域名同时发起多个长连接,用数量来解决质量问题,但是如果并发数太大,服务器会认为是恶意攻击,拒绝请求,对客户端发起并发请求的数量限制在6-8;域名分片,增加域名的数量,多个域名指向同一个服务器。

    长连接:不进行四次握手,数据传输完成TCP连接不断开,同域名下继续使用这个通道,有过期时间限制(keep-alive:timeout)

    1. 如果GET或DELETE请求,发送者带上了body,服务器应该怎样处理?

    直接忽略body的内容(可能会导致下一个接口报错);报400,参数错误;接受处理,返回空数据;丢弃Content-Length和body

    1. 撰写测试用例

    相关文章

      网友评论

          本文标题:HTTP协议1.1

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