Network programming based on Node
- Node is a network oriented platform
- Node is event-driven, non-blocking, and single-threaded
- Node’s API fits well with the network, making it ideal for building flexible web services
- Node can be very convenient to build a network server, the traditional Web platform most need a special Web server as a container, such as ASP needs IIS as a server, PHP needs to carry Apache or Nginx environment
- Node provides net, Dgram, HTTP, and HTTPS modules to process TCP, UDP, HTTP, and HTTPS respectively for the server and client
A network model
Network seven layer model
In order to facilitate learning and understanding, the five-layer network model is used here
Network five layer model
Layer and protocol
Each layer of the network model is to complete a function, in order to achieve these functions, we need to abide by the common rules, the rules we abide by, is called the protocol
Physical layer
To realize networking communication between computers, they must be connected by optical cable, cable, radio wave and other physical ways. This way of physically connecting computers is called the “physical layer”, and its role is to transmit only the 0 and 1 electrical signals
The link layer
Zeros and ones alone don’t make any sense. You have to specify how to read them. How many electrical signals are in a group? What does each signal bit mean? This is the function of the “link layer”, which specifies the grouping of electrical zeros and ones on top of the “entity layer”.
Ethernet protocol
In the early days, each company had its own way of grouping electrical signals. Later Ethernet protocol gradually occupied the dominant position. The Ethernet protocol defines a group of electrical signals to form a packet, called a frame. Each frame is divided into a Head and a data
The header: contains data description items, such as the sender, receiver, data type, etc.“Data”Is the specific content of the packet
The MAC address
The header contains information about the receiver and the sender, and how they are identified. The Ethernet protocol stipulates that computers connected to the network must have a network interface, from which packets are transferred to another network interface. The MAC address of a network adapter is used to identify the addresses of communication parties and locate the path of the network adapter and data packets.
Each nic is delivered with a MAC address that is unique in the world. It is a 48-bit binary number, usually represented by 12 hexadecimal numbers
The MAC addressThe first six hexadecimal digits are the manufacturer’s SERIAL numbers, and the last six are the nic serial numbers of the manufacturer
radio
In the Ethernet protocol, communication uses a “raw” method, in which the system sends packets to all the computers in the local sub-network and lets each computer decide for itself whether it is the data recipient. For example, if there are five computers in the same subnetwork, computer no. 1 wants to send a packet to computer No. 3, all of them will receive the packet. They will read the packet header, find the MAC address of the receiver and compare it with their own MAC address. This process is called broadcast. With the definition of the packet, the MAC address of the nic, and the way the broadcast is sent, the link layer can transfer data between computers.
The network layer
Transmitting packets over broadcast is inefficient and limited. The two communication parties are not in the same subnetwork and cannot transmit data packets through broadcast. Therefore, we need to distinguish which MAC addresses belong to the same subnetwork.
The network layer uses a new set of addresses (network IP addresses) to distinguish whether different computers belong to the same subnetwork. So each computer has two addresses Mac address and network address. The MAC address is bound to the network adapter, and the network address is assigned by the network administrator. They are just randomly combined. The network address determines the subnetwork where the packet receiver resides, and the MAC address sends the packet to the destination network adapter in the subnetwork
TCP/IP protocol
The protocol that defines the network address is called IP protocol, and the address it represents becomes an IP address. Currently, IPv4 is widely used. This version specifies that the network address consists of 32 two-level bits
An IP address is usually represented by four decimal fields, that is, 0.0.0.0 to 255.255.255.255
The IP protocol has two main functions
- Assign IP addresses to each computer
- Determine which addresses are in a subnetwork
The transport layer
The computer completes the communication at the network layer and then moves up to the transport layer
port
Many programs on the computer need to use data packets. When obtaining a data packet from the Internet, how to determine which program to use, this time needs to use ports. Port is the program number of the network card, each packet sent to the host specific port, so different data can get their own data needs.
The port is an integer ranging from 0 to 65535, which is exactly 16 bits. Ports from 0 to 1023 are occupied by the system, and users can only select ports larger than 1023. The application program randomly selects a port to contact the server response port, whether browsing the web or chatting
The transport layer establishes port-to-port communication, which is also called Socket communication between client and server. In contrast, the function of the network layer establishes host-to-host communication, allowing programs to communicate with each other after identifying hosts and ports.
UDP protocol.
Adding port information to packets requires the specification of a new protocol, the simplest of which is UDP.
UDP packets are also composed of headers and data. The header of a UDP packet defines the ports for receiving and transmitting UDP packets, and the Data section contains specific data. The entire UDP packet is placed in the data part of the IP packet, and the structure relationship of the entire packet is roughly as follows from the Ethernet packet
Ethernet data packets contain Ethernet data headers + Ethernet data Ethernet data packets contain IP data headers + IP data IP data packets contain UDP data headers + UDP data
The UDP header is only 8 bytes in total, and the total length is no more than 65535 bytes, which can fit neatly into an IP packet.
The UDP protocol is unreliable and may cause data loss during data transmission. Therefore, data consistency cannot be ensured during the communication between two parties.
TCP protocol
UDP protocol, as a non-connection-oriented protocol, has unreliability. TCP is designed to solve this problem. TCP is a connection-oriented, reliable, byte stream – based transport layer communication protocol. TCP establishes a connection through a three-way handshake before sending data. If data fails to be sent for some reason, the connection is re-established. After data is sent, disconnect the system to reduce the usage of system resources.
TCP is different from UDP
Features/Protocols | TCP | UDP |
---|---|---|
Connection-oriented or not | connection-oriented | Unoriented connection |
Transmission reliability | reliable | unreliable |
Usage scenarios | A small amount of data | A large amount of data |
speed | slow | fast |
Generally speaking, TCP is connection-oriented. It has high data transmission reliability, but occupies high system resources and low transmission efficiency. TCP should be used if data integrity and order are required, for example, data in the browser or webmail. UDP is unreliable and prone to packet loss, but has high transmission efficiency. It is commonly used in large-volume data flow scenarios, such as voice calls, video calls, and live broadcasts.
The application layer
Both TCP and UDP are low-level protocols. The ones we’re dealing with are basically in the application layer. The transmission layer realizes the transmission and reception of data. Since the Internet is an open architecture and data sources are diverse, we need to formulate norms to interpret data and realize data communication between the two parties.
The application layer defines the data format of different applications. TCP transmits data for various applications, such as Email, WWW, and FTP. These applications also specify data specifications based on different protocols.
Application layer is the highest layer, it is directly facing the user, his data in the TCP packet part is as follows:
Setting up the TCP Service
To establish a TCP connection, the communication parties need to shake hands three times. After the TCP connection is successfully established, the communication starts.
TCP three-way handshake
The client first sends data to the server for the first handshake. After receiving the data, the server responds to the client and shakes hands with the client for the second time. After receiving the response, the client shakes hands with the client for the third time and sends data to the server again to inform the server that it can receive the data. After three handshakes between the client and server, the TCP connection is established and data can be transferred.
Net module
The NET module of Node can set up TCP service
// Server side
const Net = require('net')
const app = Net.createServer()
// When the client successfully establishes the connection
app.on('connection'.clientSocket= > {
console.log('Connection established successfully');
// Send data to a single currently connected client
clientSocket.write('hello')})// Start the service on port 3000
app.listen(3000.function () {
console.log('TCP service Running ');
})
/ / the client
const Net = require('net')
// The client creates the connection
const client = Net.createConnection({
// Server domain name and port number
host: '127.0.0.1'.port: '3000'
})
// The connection is successful
client.on('connect'.() = > {
console.log('Connected to server successfully');
})
// When the server responds to data
client.on('data'.data= > {
console.log('Server returns data', data.toString());
})
Copy the code
The client and server realize bidirectional communication
// Server side
// The server listens for the data sent by the client after the connection is established successfully
// When the client successfully establishes the connection
app.on('connection'.clientSocket= > {
console.log('Connection established successfully');
// Send data to the currently connected client
clientSocket.write('hello')
// Listen for the data sent by the client
clientSocket.on('data'.(data) = > {
console.log('Client transfers data:', data.toString()); })})/ / the client
// The connection is successful
client.on('connect'.() = > {
console.log('Connected to server successfully');
// Send data to the server
client.write('Hello, this is client. ')})Copy the code
The client sends terminal information to the server
Here to implement a small function, the client terminal input data sent to the server side.
/ / the client
client.on('connect'.() = > {
console.log('Connected to server successfully');
client.write('Hello, this is client. ')
// After the connection is established, the terminal input content is obtained and transmitted to the server
process.stdin.on('data'.data= > {
client.write(data)
})
})
Copy the code
Setting up the UDP Service
UDP
UDP is also known as the User Datagram Protocol
- Like TCP, UDP is used to transmit data packets at the network transport layer
- No connection, high transmission speed, unreliable data transmission, does not provide packet grouping, cannot sort packets, data is out of order, cannot ensure the integrity and correctness of data during transmission.
- UDP supports one-to-one communication and one-to-many communication.
- UDP is suitable for applications that have high requirements on transmission speed and data transmission quality. For example, streaming media, multiplayer games, real-time audio and video, etc.
UDP Propagation mode
UDP transmits data in unicast, broadcast (multicast), and multicast modes
- Unicast Unicast refers to the point-to-point, single-target transmission of UDP. The address range is 0.0.0.0 to 223.255.255.255
- radio
UDPAlso supportsradioTransmitting data in the form of,radioThe target address is all devices in the current LAN
Address range is divided intoLimited radio 和 Direct broadcast- Restricted broadcasts are broadcast only on the current route or switch and are not forwarded to other routes. The network and host fields of the target IP address in restricted broadcast are all 1, that is, the address is 255.255.255.255
- Direct broadcasts are routed and forwarded. The IP address network field defines this address, and the host field is 1, for example, 192.168.10.255
- multicast
Both broadcast and multicast transmit data one-to-many. Multicast transmits the same data to a group of target hosts, broadcast transmits data to all hosts on the LAN, and multicast combines multiple components and sends data.
Application of different propagation in one-to-many scenarios
- Unicast The one-to-many server transmits data to multiple hosts in unicast mode over UDP. Multiple unicast packets need to be sent with the same number of times as the number of receivers, and each packet contains the exact IP address of the destination host. If there are hundreds or thousands of recipients, you add to the burden on the server.
- Broadcast implementation one-to-many broadcasting is restricted to the LAN. Once a device sends broadcast data, all devices in the broadcast domain receive the data and consume resources to process it. A large number of broadcast packets will consume network bandwidth and device resources in IPV6, broadcast packet transmission mode is cancelled
- Multicast Implementation One-to-many multicast is suitable for one-to-many transmission scenarios. Only the host that joins a specific multicast group can receive multicast data. When transmitting multicast packets, you can send only one packet without sending multiple packets. The multicast device forwards or copies the multicast data according to the situation. The same multicast packet has only one packet on the same link, which greatly improves the utilization of network resources.
Dgram module
In Node, the Dgram module is used to build UDP services. Dgram is used to create sockets that can either receive data as a client or send data as a server
const dgram = require('dgram')
const socket = dgram.createSocket('udp4')
Copy the code
The method of the socket
API | instructions |
---|---|
bind() | Bind a port to a host |
address() | Returns the Socket address object |
close() | Close the Socket and stop the listening |
send() | Send a message |
addMembership() | Add a multicast member |
dropMembership() | Example Remove a multicast member |
setBroadcast() | Set whether to enable broadcast |
setTTL() | Set the datagram survival time |
setMulticastTTL() | Set the multicast datagram survival time |
The socket events
The event name | trigger |
---|---|
listening | Triggered only once when the listener succeeds |
message | Triggered when a message is received |
error | Triggered when an error occurs |
close | Triggered when the socket is closed |
UDP unicast implementation
The server side
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// Triggered when the port number is successfully bound
server.on('listening'.() = > {
const address = server.address()
console.log('Server running on:' + address.address + ':' + address.port);
})
// Triggered when a message is received
server.on('message'.(msg, remoteInfo) = > {
console.log('The server received a message from:${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
// Send information to the client
server.send('Hello client, this is server.', remoteInfo.port, remoteInfo.address);
})
// Triggered when an error occurs
server.on('error'.err= > {
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
// Bind the service to a port to run
server.bind(3000)
Copy the code
The client
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
// Send information to localhost:3000
client.send('hello world'.3000.'localhost')
// Triggered when the port number is successfully bound
client.on('listening'.() = >{
const address = client.address()
console.log('Client runs on:'+address.address+':'+address.port);
})
// Triggered when a message is received
client.on('message'.(msg,remoteInfo) = >{
console.log('The client received a message from:${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
})
// Triggered when an error occurs
client.on('error'.err= >{
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
Copy the code
UDP broadcast implementation
The client
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
client.on('listening'.() = > {
const address = client.address()
console.log('Client running on' + address.address + ':' + address.port);
})
client.on('message'.(msg, remoteInfo) = > {
console.log('The client receives a message from${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
})
client.on('error'.err= > {
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
// The client binding runs on port 8000
client.bind(8000)
Copy the code
The server side
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// The number of broadcasts
let sendTime = 1
server.on('listening'.() = > {
const address = server.address()
console.log('Server running on' + address.address + ':' + address.port);
// Enable the broadcast transmission mode after the service runs successfully
server.setBroadcast(true)
// Close the broadcast
// server.setBroadcast(false)
// Broadcast data every two seconds
setInterval(() = > {
server.send('Hello client, I am server side broadcast data *' + sendTime++, 8000.'255.255.255.255');
}, 2000)
})
server.on('message'.(msg, remoteInfo) = > {
console.log(The server received a message from${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
server.send('Hello client, this is server.', remoteInfo.port, remoteInfo.address);
})
server.on('error'.err= > {
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
// Bind the service to a port to run
server.bind(3000)
Copy the code
UDP multicast implementation
The client
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
client.on('listening'.() = > {
const address = client.address()
console.log('Client running on' + address.address + ':' + address.port);
// The current client was added to the multicast group
client.addMembership('224.0.1.100')
})
client.on('message'.(msg, remoteInfo) = > {
console.log('The client receives a message from${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
})
client.on('error'.err= > {
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
// The client binding runs on port 8000
client.bind(8000)
Copy the code
The server side
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// Multicast times
let sendTime = 1
server.on('listening'.() = > {
const address = server.address()
console.log('Server running on' + address.address + ':' + address.port);
// Multicast data every two seconds
setInterval(() = > {
server.send('Hello client, I am server-side multicast data *' + sendTime++, 8000.'224.0.1.100');
}, 2000)
})
server.on('message'.(msg, remoteInfo) = > {
console.log(The server received a message from${remoteInfo.address}:${remoteInfo.port}Information:${msg}`);
server.send('Hello client, this is server.', remoteInfo.port, remoteInfo.address);
})
server.on('error'.err= > {
console.log('An error has occurred.The ${JSON.stringify(err)}`);
})
// Bind the service to a port to run
server.bind(3000)
Copy the code
Setting up the HTTP Service
TCP and UDP are network transport layer protocols that can build efficient network applications, but transport layer protocols can be cumbersome for classic browser and server communication scenarios. For the above scenario, based on the transport layer to develop a higher layer of communication protocol: HTTP, because HTTP protocol itself does not consider how to transmit data and other details, so he belongs to the network application layer. Node provides HTTP and HTTPS modules for HTTP and HTTPS encapsulation
The HTTP module
const HTTP = require('http')
const server = HTTP.createServer()
Copy the code
Server method
methods | instructions |
---|---|
close | Close the service |
listening | Obtaining service Status |
Server events
methods | instructions |
---|---|
close | Close the service |
require | Obtaining service Status |
Request object Request
attribute | instructions |
---|---|
method | Request way |
url | Request the address |
headers | Request header |
httpVersion | Request HTTP protocol version |
Response object Response
API | instructions |
---|---|
end() | The end of the response |
setHeader(name,value) | Setting the response header |
removeHeader(name,value) | Delete the response header |
statusCode | Set the response status code |
write | Write response data |
writeHead | Write response header |
Create a basic HTTP service
const HTTP = require('http')
const hostName = '127.0.0.1'
const port = 3000
const server = HTTP.createServer((req, res) = > {
// Set the response status code
res.statusCode = 200
// Set the response status code. Set the response body to text
res.setHeader('Content-Type'.'text/plain')
// End the response and return data
res.end('Hello World\n')})// The service is running successfully
server.listen(port, hostName, () = > {
console.log(The service runs on:${hostName}:${port}`)})Copy the code
Access to the url
const http = require('http')
const port = 3000
const hostName = '127.0.0.1'
const server = http.createServer((req, res) = > {
/ / get the url
const url = req.url
if (url === '/') {
res.end('Hello Home')}else if (url === '/a') {
res.end('Hello A')}else if (url === '/b') {
res.end('Hello B')}else {
// The interface is accessed successfully. The response status code is set to 200 by default
res.statusCode = 404
res.end('404 Not Found')
}
})
server.listen(port, hostName, () = > {
console.log('Service running successfully');
})
Copy the code
Responding to HTML content
HTTP response content is text format by default, you can set the response header to respond to THE HTML content
const http = require('http')
const port = 3000
const hostName = '127.0.0.1'
const server = http.createServer((req, res) = > {
// Set the response header and return the content in HTML format. Utf-8 is used to avoid Chinese garbled characters
res.setHeader('Content-Type'.'text/html; charset=utf-8')
res.end('Hello World>
)
})
server.listen(port, hostName, () = > {
console.log('Service running successfully');
})
Copy the code
Handle static resources in a project
When the HTML content of the backend response contains static resources, these static resources are also sent to the backend as a request.
- Create index. HTML and return HTML to the front end when accessing the root path
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
<link rel="stylesheet" href="./assets/css/index.css">
</head>
<body>
<h1>Hello World</h1>
<div>Hello world</div>
<script src="./assets/js/index.js"></script>
</body>
</html>
Copy the code
- Create an assets folder to store CSS and JS files
/* assets/css/index.css */
h1 {
color: pink;
}
// assets/js/index.js
console.log('Assets /index.js loaded');
Copy the code
- Setting up web Services
const http = require('http')
const fs = require('fs')
const path = require('path')
const port = 3000
const hostName = '127.0.0.1'
const server = http.createServer((req, res) = > {
/ / get the url
const url = req.url
// Access the root path to return the HTML resource
if (url === '/') {
// Get the absolute path to the HTML resource
const HTML_Path = path.resolve(__dirname, 'index.html')
fs.readFile(HTML_Path, (err, data) = > {
if (err) throw err
// Set the response status code
res.statusCOde = 200
// Set the text type and encoding format of the response content
res.setHeader('Content-Type'.'text/html; charset=utf-8; ')
// Respond to the HTML resource
res.end(data)
})
// Access CSS resources in Html
} else if (url === '/assets/css/index.css') {
// Obtain the absolute path of the CSS resource
const HTML_Path = path.resolve(__dirname, 'assets/css/index.css')
fs.readFile(HTML_Path, (err, data) = > {
if (err) throw err
// Set the response status code
res.statusCOde = 200
// Set the text type and encoding format of the response content
res.setHeader('Content-Type'.'text/css; charset=utf-8; ')
// Respond to the HTML resource
res.end(data)
})
} else if (url === '/assets/js/index.js') {
// Get the absolute path of the js resource
const HTML_Path = path.resolve(__dirname, 'assets/js/index.js')
fs.readFile(HTML_Path, (err, data) = > {
if (err) throw err
// Set the response status code
res.statusCOde = 200
// Set the text type and encoding format of the response content
res.setHeader('Content-Type'.'text/javascript; charset=utf-8; ')
// Respond to the HTML resource
res.end(data)
})
}
})
server.listen(port, hostName, () = > {
console.log('Service running successfully');
})
Copy the code
Unified processing of resources
In the above operations, static resources are processed. However, the separate judgment processing of each resource increases a lot of repeated codes, which is not conducive to the maintenance work of adding other types of resources in the later period. Resources can be uniformly processed here.
- Only requested urls that begin with /assets/ are considered to be requesting resources
- The NPM package MIME can be used to obtain the HTTP content format based on the file name extension. For example, the.css resource type is Text/CSS
const http = require('http')
const fs = require('fs')
const path = require('path')
const mime = require('mime')
const port = 3000
const hostName = '127.0.0.1'
const server = http.createServer((req, res) = > {
/ / get the url
const url = req.url
// Access the root path to return the HTML resource
if (url === '/') {
// Get the absolute path to the HTML resource
const HTML_Path = path.resolve(__dirname, 'index.html')
fs.readFile(HTML_Path, (err, data) = > {
if (err) throw err
// Set the response status code
res.statusCOde = 200
// Set the text type and encoding format of the response content
res.setHeader('Content-Type'.'text/html; charset=utf-8; ')
// Respond to the HTML resource
res.end(data)
})
} else if (url.startsWith('/assets/')) {
// Obtain the resource path
const assetsPath = path.resolve(__dirname, url)
fs.readFile(assetsPath, (err, data) = > {
if (err) throw err
// Set the response status code
res.statusCOde = 200
const type = mime.getType(url)
// Set the text type and encoding format of the response content
res.setHeader('Content-Type', type + '; charset=utf-8; ')
})
}
})
server.listen(port, hostName, () = > {
console.log('Service running successfully');
})
Copy the code
Establishing the HTTPS Service
The HTTP protocol is very insecure, and it has the following risks
- Communications are intercepted, and a third party can intercept and view communications
- A third party can intercept and modify a communication when the content is tampered with
- The communication identity is impersonated, and the third party can impersonate the client and server to participate in the communication
To solve these problems, HTTPS is the HTTP protocol based on TLS/SSL. In HTTP, data is transmitted in plaintext, while HTTPS encrypts data for transmission. So HTTPS is kind of a secure version of HTTP.
HTTPS = HTTP +SSL/TLS During HTTPS data transmission, SSL or TLS is used to encrypt and decrypt data, and HTTP is used to transmit encrypted data. TLS/SSL is a pair of public and private keys. The transmitted data is encrypted symmetrically and the encrypted key is encrypted asymmetrically, ensuring data security to a certain extent. However, it still cannot solve the problem that a third party impersonates itself to participate in communication. For example, normally the client communicates directly with the server. If a third party intervenes, it can disguise itself as the server intercepts the key pair, causing data leakage.
To solve the problem of third parties posing as identities, TLS/SSL introduces digital certificates for authentication. Digital certificates are a digital authentication of the identities of the parties involved in network communication. People can use them to identify each other online. He differs from the direct use of public key and digital certificate contains the name of the server and the host name, server’s public key, signature authority, from the name of the signature authority of signature, before the connection is established, through signature acknowledges receipt of the public key certificate is from the target server, rather than pretending to be the identity of the server. A digital certificate is issued by a third-party digital certificate authority (CA), which also has many agents, such as Alibaba and Tencent.
Simulate a CA to generate a local certificate
Digital certificates can be applied for in Ali, Tencent, most of which are charged and the server for digital certificates has domain name and other requirements. Here only simulate CA institutions to generate local certificates
// Execute the following code to generate the local certificate
openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt
Copy the code
Certificate, private key, and public key are all generated by OpenSSL. To use OpenSSL, you need to install the configuration environment first. For details, please go to advanced [1] — Core API
Setting up the HTTPS Server
const https = require('https');
const fs = require('fs');
const options = {
// Bind public and private keys
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert:fs.readFileSync('test/fixtures/keys/agent2-cert.pem')}; https.createServer(options,(req, res) = > {
res.writeHead(200); res.end('hello world\n');
}).listen(8000);
Copy the code