TCP


TCP corresponds to the transport layer, while HTTP corresponds to the application layer. In essence, the two are not comparable. However, HTTP is based on the TCP protocol.

TCP/IP layer 7 model


The physical layer The link layer
The binary 0 and 1 and voltage high and low, light flicker off and radio wave strong and weak signal conversion drive

The network layer

- IP is an unreliable protocol and cannot be retransmitted. - IP fails to send packets and ICMP fails to notify them. - ARP resolves MAC addresses in IP. The MAC address is provided by the nic. - IP also provides the link layer function, enabling both sides to communicate regardless of the underlying link layerCopy the code

Common TCP and UDP protocols at the transport layer (TCP is more secure than UDP)

TCP is connection-oriented and can correctly handle packet loss and transmission order disorder. However, to establish and disconnect a connection, at least seven packets are sent and received, which wastes resources. UDP is connection-oriented and requires notification through the application layer regardless of whether the other party has received the notificationCopy the code

Layer above the Session Layer In the TCP/IP layer, the session layer, presentation layer, and application layer are centralized and the network is managed through SNMP

HTTP

The Http protocol is based on the TCP protocol. When the browser needs to fetch web page data from the server, it sends an Http request. Http establishes a connection channel to the server through TCP, and immediately disconnects the TCP connection when the required data is completed. This process is very short. So an Http connection is a short, stateless connection.

Keep-alive HTTP does not have any status, but it can be reused through sessions, such as sessions, to save bridge disassembly time.

Status code


1XX 2XX 3XX 4XX 5XX
Informational status code Success status code redirect Client error status code Server error status code
rare 200 OK 301 Permanent redirect 400 The request packet syntax is incorrect 500 Server request error
  204 The response packet does not contain the body part of the entity 302 Temporary Redirection (Load Balancing) The request sent by 401 must have HTTP authentication information 307 and 302 have the same meanings 503 The server is overloaded or is being stopped for maintenance and cannot process requests
  206 Range Request 303 Another URL exists for the resource and you should use the GET method to GET the resource directionally 403 Access to the requested resource was denied by the server  
    The 304 client has performed GET, but the file has not changed. 404 Requested resource not found on server  

Console. log Error status code


  • A SyntaxError is a SyntaxError that occurs when parsing code
  • Uncaught ReferenceError: indicates a ReferenceError
  • RangeError: RangeError
  • TypeError Indicates an error type
  • URIError, URL error
  • EvalError The eval() function is executing incorrectly
  1. Today we are going to talk about HTTP at the network layer; We know that HTTP is used to write to the server, so what can it do? Examples include Ajax interactions, status codes {304: server caching issues, 206: range requests (partial requests)}, compression {Content-Encoding:gzip deflate}, image anti-theft, encryption issues {symmetric, asymmetric}, server proxies (forward proxies, reverse proxies)

Write a static service (command line tool)

What happens when you enter the URL to the page load?


Three times handshake


Client – Sends packets with the SYN flag – One handshake – Server Server – Sends packets with the SYN/ACK flag – Two handshake – Client Client – Sends packets with the ACK flag – Three handshake – Server

4 times to wave


Client – sends a FIN to shut down the client-to-server data transfer server – receives the FIN, it sends back an ACK confirming the received sequence number plus one. Similar to the SYN, a FIN occupies a sequence number. The server closes the connection with the client and sends a FIN to the client. The client sends back an ACK packet to acknowledge receipt and sets the sequence number to 1

** This step includes the DNS search process, including: browser cache -> system cache -> router cache... > The browser sends an HTTP request to the Web server > the server's permanent redirection response (from http://example.com to http://www.example.com) > the browser traces the redirection address > the server processes the request > the server returns one HTTP Response > Browser displays HTML > The browser sends a request for resources embedded in HTML (such as images, audio, video, CSS, JS, and so on) >. The browser sends an asynchronous request **Copy the code

pipelines

Can handle concurrency

URI url urn

Uri Uniform resource representation, URL uniform resource locator location, uniform resource name

An url

> http://(protocol)name:password(login information, authentication)@www.fs.ip(server address):8080(port number)/dir/index.htm(file path)? A =a(query string)#asd(fragment identifier)Copy the code

We go to a path, we go back to the DNS domain and we look for the IP address, we look in the browser cache, we look in local files and so on, and we return the IP address, HTTP is for the application layer, the application layer will have some packets, mostly through TCP, HTTP is based on TCP, TCP will break up HTTP into many segments, Each udp packet is reliably transmitted to the peer. Udp packets are discarded and returned to the server after being completed

Url module of node

let url = require('url');

let Obj  = url.parse('http://user:[email protected]:80/1.html?a=1#aaa')
console.log(Obj);

=>Url {
  protocol: 'http:'.slashes: true.auth: 'user:passwrd'.host: 'www.zdl.cn:80'.port: '80'.hostname: 'www.zdl.cn'.hash: '#aaa'.search: '? a=1'.query: 'a=1'.pathname: '/1.html'.path: '/1.html? a=1'.href: 'http://user:[email protected]:80/1.html?a=1#aaa' }
Copy the code

We usually parse strings

let url = require('url');

let {pathname ,query,path}  = url.parse('http://user:[email protected]:80/1.html?a=1&b=2&c=3&d=4#aaa')
/ / parsing
let str = query;
let obj = {};
str.replace(/([^=&]*)=([^=&])/g.function(){
    obj[arguments[1]] = arguments[2];
})

console.log(obj);
/ / or
let {pathname ,query,path}  = url.parse('http://user:[email protected]:80/1.html?a=1&b=2&c=3&d=4#aaa'.true) // Adding true resolves directly
/ / parsing
console.log(query);
Copy the code

The above request message includes the request line, the request header, the request entity (all with content are entities), and then the request will return a response header. Both the request header and the response header have common header fields, and the request header has unique header fields called request header fields.

The difference between HTTP and TTP is the packet, which is a protocol that does not save but can keep the state

Restful style

Get POST PUT DELETE head Get the packet header options cross-domain exploratory request, save traffic TeACE call table, trace path

Scope of the request

curl -v --header "Range:bytes=1-200" https://www.baidu.com/img/bd_logo1.png?qua=high =>subjectAltName: host "www.baidu.com" matched cert's "*.baidu.com" * issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign Organization Validation CA - SHA256 - G2 * SSL certificate verify ok. > GET /img/bd_logo1.png? Qua =high HTTP/1.1 > Host: www.baidu.com > user-agent: curl/7.54.0 > Accept: */* > Range:bytes=1-200 > < HTTP/1.1 206 Partial Content < accept-ranges :bytes < cache-control: max-age=315360000 < Connection: Keep-Alive < Content-Length: 200 < Content-Range: bytes 1-200/7877 < Content-Type: image/png < Date: Sat, 07 Jul 2018 03:56:46 GMT < Etag: "1ec5-502264e2ae4c0" < Expires: Tue, 04 Jul 2028 03:56:46 GMT < Last-Modified: Wed, 03 Sep 2014 10:00:27 GMT < P3p: CP=" OTI DSP COR IVA OUR IND COM " < Server: Apache < Set-Cookie: BAIDUID=B37F40A5E737D32A9475DC95E0925B45:FG=1; expires=Sun, 07-Jul-19 03:56:46 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1 < PNGCopy the code

For a Range request with multiple ranges, the response identifies multipart/ Byteranges in the content-Type header

Write a service using TCP

let http = require('http')

let server = http.createServer();
server.on('request'.function(req,res){
    console.log("Here comes the request.");
    // Both req and RES streams are socket - based req readable streams => client, res readable streams => server
    //res.writeHead(200,{... }) can be written once, and conflict with setHeader
    res.statusCode = 200;
    res.setHeader('Content-Length'.2);
    res.setHeader('Content-Type'.'text/html; charset=utf8');
    res.end('hello');
    // The request can be sent through the server, curl, postman, etc
})
// The default connection resolves the socket into two things: req and RES
server.on('connection'.function(socket){
    //net socket has the same effect as res
// socket.write(`
/ / HTTP / 1.1 200 OK
// Content-Length :2
// Content-Type: text/html; charset=utf8

// ok
/ / `)
// socket.end()
    console.log("Link successful");
    
})
server.listen(3000)
Copy the code

The difference between POST and GET

  • Post has a request body, so we can put the content we pass into the request body
  • Get is passed at the URL,
  • Post may seem relatively secure, but it is not
  • Get can only send 64K posts and can send many

The HTTP application

// Command line input test
//curl -X POST -v  -d "name=zdl" http://localhost:3000/a?a=1&c=4
let http = require('http')

let server = http.createServer();
server.on('request'.function(req,res){
    console.log(req.method);
    console.log(req.url);
    console.log(req.httpVersion);
    console.log(req.headers);// The request header object, which can be used to retrieve the argument inside, can be used to retrieve (lowercase)
    let arr = [];
    req.on('data'.function(data){// If a POST needs to listen for data, the default trigger is 64K once
        arr.push(data)
    })
    req.on("end".function(){
        let str = Buffer.concat(arr);
        console.log(str.toString());
        res.end('hello');
    })
})
server.listen(3000.function(socket){
    console.log("server start 3000");
})

Copy the code

Simulate HTTP with TCP


// Test the command line input
let net = require('net');
let server = net.createServer();
function parser(socket,callback){
    // socket.on("data",function(){

    / /}) / / receiving

    function parserHeader(head){
        let obj = {};
        let headers = head.split(/\r\n/);
        let line = headers.shift();
        let [method,path,version] = line.split(' ');
        let heads = {};
        headers.forEach(line= > {
            let [key,value] = line.split(':');
            heads[key] = value;
        });
        obj['method'] = method;
        obj['path'] = path;
        obj['version'] = version;
        obj['headers'] = headers;
        return obj;
        
    }
    function fn(){
        let result = socket.read().toString();// If the read parameter is not passed, the default is full read
        let [head,content] = result.split(/\r\n\r\n/);
        let obj = parserHeader(head);
        console.log(obj);
        // The readble method fires multiple times and is removed once
        socket.removeListener('readable',fn)
        
    }
    socket.on("readable",fn)// The cache is filled up by default
}
server.on('connection'.function(socket){
    parser(socket,function(req,res){
        server.emit('request',req,res);// Send the socket to request
    })
})
server.on('request'.function(req,res){
    console.log(req.method);
    console.log(req.url);
    console.log(req.httpVersion);
    console.log(req.headers);// The request header object, which can be used to retrieve the argument inside, can be used to retrieve (lowercase)
    let arr = [];
    req.on('data'.function(data){// If a POST needs to listen for data, the default trigger is 64K once
        arr.push(data)
    })
    req.on("end".function(){
        let str = Buffer.concat(arr);
        console.log(str.toString());
        res.end('hello');
    })
})
server.listen(3000)
Copy the code

Application of HTTP headers

The things that we use a lot, breakpoint continuation, multilingualism and anti-theft are all based on our HTTP, including caching,

Breakpoint continuation, segmented request, the segmented request mentioned above (range:bytes=0-3)

  • Client request header Range:bytes=1-200

  • The service side

Response header Accept-ranges: bytes < Content-Length: 200 < Content-range: bytes 1-200/7877

Simulate the above functions

range.js

/ / the server
let http = require('http');
let path = require('path');  / / path
let fs = require('fs'); / / read the file
let p = path.join(__dirname,'1.txt'); // Get the path to read the file
let {promisify} = require('util');
let stat = promisify(fs.stat); // Methods that convert stat methods to promises may not have end read all by default
let server = http.createServer();
server.on('request'.async function (req,res) {
    // retrieve the request header; otherwise, retrieve the whole header
    let range = req.headers['range'];
    try{
        let s = await stat(p);
        let size = s.size;
        if (range) {
            let [, start, end] = range.match(/(\d*)-(\d*)/);// The first argument is the matching string, the second is the first item, and the second is the second item
            start = start ? Number(start) : 0;
            end = end ? Number(end)- 1 : size- 1;
            res.statusCode = 206;
            // Tell the client that it is a range request
            res.setHeader('Accept-Ranges'.'bytes');
            // The length of the content returned
            res.setHeader('Content-Length',end-start+1);
            res.setHeader('Content-Range'.`bytes ${start}-${end}/${size}`); 
            fs.createReadStream(p,{start,end}).pipe(res); // Pass the read results to res
        } else {
            // Return the file while reading
            fs.createReadStream(p).pipe(res);// The res stream is writable, and the pipeline between the readable stream and the writable stream is equivalent to continuously reading the file}}catch(e){
        console.log(e);
        
    }
})
server.listen(3000); 

Curl -v --header "Range:bytes=3-5" http://localhost:3000
Copy the code

Implement download function

client.js

// Start the server upstairs, and then run the client in CMD with the name of the current node folder
let http = require('http');
let fs = require('fs');
let pause = false; // Download mode is paused when true is enabled by default
let ws = fs.createWriteStream('./download.txt');// I want to download it to this place
let options = {
    hostname: 'localhost'.// host/path
    port: 3000.// The port number is 0-3/3-5 and so on
}
// Implement the download function
let start = 0;
// Monitor input
process.stdin.on('data'.function (data) {
    data = data.toString();
    if(data.match(/p/)){
        pause = true;
    }else{
        pause = false; download(); }})function download() {
    // The request is preceded by a request header
    options.headers = {
        'Range': `bytes=${start}-${start + 9}`
    }
    start += 10;
    // let socket = http.request(options); // The file location requested for each call is accumulated
    // socket.write();
    // socket.end()// Send the request
    / / is equivalent to
    http.get(options, function (res) { // Multiple requests are sent
        let buffers = [];
        let total = res.headers['content-range'].split('/') [1];
        total = parseInt(total);/ / 58
        res.on('data'.function(data){
            buffers.push(data);
        })
        res.on('end'.function () {
            let str = Buffer.concat(buffers).toString();
            ws.write(str);// Write to the file
            if(! pause && start < total) {// Continue until the request is complete
              setTimeout((a)= > {
                download()
              }, 1000); }}); }) } download();Copy the code

Preventing hotlinking

  • Find a picture in Baidu

      
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js"></script>
</head>
<body>
    <img src="http://d.hiphotos.baidu.com/video/pic/item/e850352ac65c10385fd7b21fbe119313b17e8945.jpg" alt="">
</body>
</html>
Copy the code

When the http-server is used to start the server, the result picture appears split graph, which is a simple anti-theft, the principle is very simple, Referer: if the current request is not allowed to access, return split graph

File structure

index.html

<body>
    <img src="http://localhost:3000/2.jpg" alt="">
</body>
Copy the code
let http = require('http');
let path = require('path');
let url = require('url');
let fs = require('fs');
let {promisify } = require('util');
let stat = promisify(fs.stat);

let whiteList = ['www.zdl1.cn'];
let p = path.resolve(__dirname,'public');
let server = http.createServer(async function(req,res){
    let {pathname} = url.parse(req.url); // index.html 2.jpg 1.jpg
    let refer = req.headers['referer'] || req.headers['referred'];
    try{
        let rp = path.join(p,pathname); // The real path
        let s = await stat(rp); // If the file exists, it will be read to the client
        if(refer){
            // return a split graph if it is illegal
            // Where can I use this map www.zdl2.cn
            let hostname = url.parse(refer).hostname;
            // represents the host name of the current file www.zdl1.cn
            let host = req.headers['host'].split(':') [0];
            if(host ! = hostname ){if (whiteList.includes(hostname)){
                return fs.createReadStream(path.join(p, '2.jpg')).pipe(res);
                }
                fs.createReadStream(path.join(p,'1.jpg')).pipe(res);
            }else{
                fs.createReadStream(path.join(p, '2.jpg')).pipe(res); }}else{ fs.createReadStream(rp).pipe(res); }}catch(e){
        res.end(`NOT Found`);
    }
})

server.listen(3000);

Copy the code

Use http://localhost:8080 to access the index file, which is the same as http://www.zdl1.cn:8080/, and http://www.zdl2.cn:8080 to return the split graph

The host file must be configured for the domain name

multilingual

Multilingual heads are also used

  • Request header format Accept-language: accept-language: zh-cn,zh; Q =0.9(l browser sends by default)
  • Response header format Content-language :zh-CN

language.js

/ / language
let pack = {
    'zh-CN':'hello'.'zh':'nihao'.'en':'hello'.'fr':'Bonjour'
}
let defaultLanguage = 'en'; // The default is English
let http = require('http');
http.createServer(function (req,res) {
    let lang = req.headers["accept-language"];
    if(lang){ // If there are multiple languages
        let langs = lang.split(', ');// Separate languages by commas
        / / [{name: 'useful - CN, q: 1}, {name:' en ', q: 0.8}]
        langs = langs.map(l= >{
            let [name,q] = l.split('; ');
            q = q?Number(q.split('=') [1) :1;
            return {name,q}
        }).sort((lan1,lan2) = >lan2.q-lan1.q);
        for(var i = 0; i<langs.length; i++){// Loop through each language to see if there is one in the package, and return the corresponding language if there is one
            if(pack[langs[i].name]){
                res.setHeader('Content-Language', langs[i].name);
                res.end(pack[langs[i].name]);
                return; }}// No default language
        res.setHeader('Content-Language'.'en')
        res.end(pack[defaultLanguage]);// Default language;
    }else{
        res.setHeader('Content-Language'.'en')
        res.end(pack[defaultLanguage]);// Default language;
    }
}).listen(3000);
//accept-language: zh-CN,zh; Q = 0.7, en. Q = 0.8, fr. Q = 0.1
Copy the code

Curl -v –header “Accept-language :zh; n; Q = 0.8, fr. q=1” http://localhost:3000

This package background is generally written by ourselves, the front end is a package such as I8N

  • Reference: Bai Weiye