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
- 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