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