WEB server learning notes
1, Build a static web server
1. What is a static Web server?
A program that can provide static documents for the requesting browser. Usually, when we browse Baidu news, the news data will change every day. The page we visit is dynamic, while what we develop is static, and the data of the page will not change.
2. How to build Python's own static Web server?
Be sure to switch to the specified resource directory before executing the following command.
Build Python's own static Web server and use python3 -m http Server port number. The rendering is as follows:
-m identifies the module in the running package. When executing this command, you need to enter the directory of the static file you specify, and then you can access the corresponding html file through the browser. In this way, a static web server is built.
3. Access the built static server
Visit the built static web server through the browser, and the renderings are as follows:
You can see the request header, GET mode request, and the request path is the index under the current path HTML IP address is localhost (local address) port number: 9000
4. Summary
- A static Web server is a program that provides static documents to the requesting browser
- Build Python's own Web server and use python3 -m http The server port number command is sufficient. If the port number is not specified, it is 8000 by default
2, Static web server - return fixed page data
1. Develop your own static web server
Implementation steps:
- Write a TCP server program
- Obtain the http request message data sent by the browser
- Read the fixed page data, assemble the page data into HTTP response message data and send it to the browser
- After sending the HTTP response message data, close the socket serving the client
2. Static Web server - returns the instance code of fixed page data
import socket if __name__ == '__main__': # Create a tcp server socket (this socket is only used to establish a connection) tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # IPv4 TCP protocol # Set the port number reuse, and the port number will be released immediately after the program exits tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # Binding port number tcp_server_socket.bind(("",9000)) # Set the maximum number of listeners tcp_server_socket.listen(128) while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket,ip_port = tcp_server_socket.accept() # The code execution here indicates that the connection is successful recv_data = new_socket.recv(4096) print(recv_data) with open("index.html","r",encoding="utf-8") as file: # The file here represents the object to open the file file_data = file.read() # Read data from file # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = response_line + response_header + "\r\n" + response_body new_socket.send(response.encode("utf-8")) # Coding required: utf-8 # Close the socket on the server new_socket.close()
3, Static server - returns the instance code of the specified page data
import socket def H(self): # Create a tcp server socket (this socket is only used to establish a connection) tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP protocol # Set the port number reuse, and the port number will be released immediately after the program exits tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # Binding port number tcp_server_socket.bind(("", 9000)) # Set the maximum number of listeners tcp_server_socket.listen(128) while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket, ip_port = tcp_server_socket.accept() # The code execution here indicates that the connection is successful recv_data = new_socket.recv(4096) # print(recv_data) # If the accepted data length is 0, close the socket if len(recv_data) == 0: new_socket.close() return # First decode the binary data recv_content = recv_data.decode("'utf-8") print(recv_content) # Divide the data into spaces request_list = recv_content.split(" ", maxsplit=2) # Split twice and return a tuple # Gets the path of the requested resource request_path = request_list[1] # The second item of the tuple is the requested resource path print(request_path) # Judge whether the requested is the root directory. If it is the root directory, set the returned information if request_path == "/": request_path = "/index.html" with open("static" + request_path, "rb") as file: # The file here represents the object to open the file file_data = file.read() # Read data from file # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 # Close the socket on the server new_socket.close() # Returns the specified page data if __name__ == '__main__': H()
4, Static server - return to page 404
import socket def H(): # Create a tcp server socket (this socket is only used to establish a connection) tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP protocol # Set the port number reuse, and the port number will be released immediately after the program exits tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # Binding port number tcp_server_socket.bind(("", 9000)) # Set the maximum number of listeners tcp_server_socket.listen(128) while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket, ip_port = tcp_server_socket.accept() # The code execution here indicates that the connection is successful recv_data = new_socket.recv(4096) # print(recv_data) # If the accepted data length is 0, close the socket if len(recv_data) == 0: new_socket.close() return # First decode the binary data recv_content = recv_data.decode("'utf-8") print(recv_content) # Divide the data into spaces request_list = recv_content.split(" ", maxsplit=2) # Split twice and return a tuple # Gets the path of the requested resource request_path = request_list[1] # The second item of the tuple is the requested resource path # print(request_path) # Judge whether the requested is the root directory. If it is the root directory, set the returned information if request_path == "/": request_path = "/index.html" # Find out if the file path exists # 1. os.path.exits os.path.exits("static/" + request_path) # 2. try-except try: with open("static" + request_path, "rb") as file: # The file object here represents the open file file_data = file.read() # Read data from file except Exception as e: # When the code is executed to this point, it indicates that the file is not requested to return 404 status information # Response line response_line = "HTTP/1.1 404 Not Found\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Read data from 404 pages with open("static/NotFound.html","rb") as file: file_data = file.read() # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 else: # There is this path to send data # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 # Close the socket on the server new_socket.close() # Returns the specified page data if __name__ == '__main__': H()
5, Static Web server - multitasking
1. Problems with static Web server
The current web server can not support multi-user access at the same time, and can only process the requests of clients one by one. So how to develop a multi task web server to process the requests of multiple clients at the same time
Multithreading can be used to save memory resources more than processes
Implementation steps of multitasking web server program:
- When the connection between the client and the server is established successfully, a sub thread is created, and the sub thread is used to process the request of the client to prevent the main thread from blocking
- Set the created sub thread to guard the main thread to prevent the main thread from being unable to exit
Test code:
import socket import threading def Handle(new_socket): # Description of successful connection to code here recv_data = new_socket.recv(4096) # print(recv_data) # If the accepted data length is 0, close the socket if len(recv_data) == 0: new_socket.close() return # First decode the binary data recv_content = recv_data.decode("'utf-8") print(recv_content) # Divide the data into spaces request_list = recv_content.split(" ", maxsplit=2) # Split twice and return a tuple # Gets the path of the requested resource request_path = request_list[1] # The second item of the tuple is the requested resource path # print(request_path) # Judge whether the requested is the root directory. If it is the root directory, set the returned information if request_path == "/": request_path = "/index.html" # Find out if the file path exists # 1. os.path.exits os.path.exits("static/" + request_path) # 2. try-except try: with open("static" + request_path, "rb") as file: # The file object here represents the open file file_data = file.read() # Read data from file except Exception as e: # When the code is executed to this point, it indicates that the file is not requested to return 404 status information # Response line response_line = "HTTP/1.1 404 Not Found\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Read data from 404 pages with open("static/NotFound.html", "rb") as file: file_data = file.read() # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 else: # There is this path to send data # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 finally: # Close the socket on the server new_socket.close() def H(): # Create a tcp server socket (this socket is only used to establish a connection) tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP protocol # Set the port number reuse, and the port number will be released immediately after the program exits tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # Binding port number tcp_server_socket.bind(("", 9000)) # Set the maximum number of listeners tcp_server_socket.listen(128) while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket, ip_port = tcp_server_socket.accept() # After the connection is established, the main thread creates a child thread sub_thread = threading.Thread(target=Handle,args=(new_socket,)) # Guard main thread sub_thread.setDaemon(True) # Start the child thread to execute the corresponding task sub_thread.start() # Returns the specified page data if __name__ == '__main__': H()
5, Static web server - object oriented development
1. Develop static Web server in object-oriented way
Implementation steps:
1. Abstract the Web server providing services into a class (HTTP webserver)
2. Provide the initialization method of Web server, and create socket object in the initialization method
3. Provide a method to start the web server and let the web server process the client request operation
2. Static Web server - Test code for object-oriented development
import socket import threading class HttpWebServer(object): # Initialize and create tcp server socket def __init__(self): # Create tcp server socket self.tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # ipv4 address Tcp transmission protocol # Set the port number reuse, and the port number will be released immediately after the program exits self.tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # Binding port number self.tcp_server_socket.bind(("",9000)) # The first parameter does not write anything, which represents the local ip address # Set the maximum number of listeners self.tcp_server_socket.listen(128) # Loop accept socket def start(self): while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket, ip_port = self.tcp_server_socket.accept() # After the connection is established, the main thread creates a sub thread and calls the static method to process the client request sub_thread = threading.Thread(target=self.Handle, args=(new_socket,)) # Guard main thread sub_thread.setDaemon(True) # Start the child thread to execute the corresponding task sub_thread.start() # There is no self object in the method and the current class is not used to process the client request. It can be used as a static method @staticmethod def Handle(new_socket): # The code execution here indicates that the connection is successful recv_data = new_socket.recv(4096) # print(recv_data) # If the accepted data length is 0, close the socket if len(recv_data) == 0: new_socket.close() return # First decode the binary data recv_content = recv_data.decode("'utf-8") print(recv_content) # Divide the data into spaces request_list = recv_content.split(" ", maxsplit=2) # Split twice and return a tuple # Gets the path of the requested resource request_path = request_list[1] # The second item of the tuple is the requested resource path # print(request_path) # Judge whether the requested is the root directory. If it is the root directory, set the returned information if request_path == "/": request_path = "/index.html" # Find out if the file path exists # 1. os.path.exits os.path.exits("static/" + request_path) # 2. try-except try: with open("static" + request_path, "rb") as file: # The file object here represents the open file file_data = file.read() # Read data from file except Exception as e: # When the code is executed to this point, it indicates that the file is not requested to return 404 status information # Response line response_line = "HTTP/1.1 404 Not Found\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Read data from 404 pages with open("static/NotFound.html", "rb") as file: file_data = file.read() # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 else: # There is this path to send data # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 finally: # Close the socket on the server new_socket.close() def main(): # Create web server web_server = HttpWebServer() # Start server web_server.start() # Returns the specified page data if __name__ == '__main__': main()
3. Summary
-
Abstract the web server providing services into a class (HTTP webserver)
class HttpWebServer(object):
-
Provide the initialization method of web server, and create socket object in the initialization method
def __init__(self): # Initialize the server socket, set listening, and omit the code
-
Provide a method to start the Web server, and let the Web server handle the client request operation
def start(self): while(True): # The server always accepts the client request and returns a tuple. The first parameter is the new socket and the second parameter is the client ip new_socket,ip_port = self.tcp_server_socket.accept() # After the connection is established, a sub thread is opened to process the client's request sub_thread = threading.Thread(target = self.Handle,args=(new_socket,)) sub_thread.start() # Open child thread
6, Static WEB server - get terminal command line parameters
import sys # Get the command line parameter of the terminal, and pass in the parameter list after the python interpreter params = sys.argv # z this is a list print(params,type(params))
design sketch:
7, Static Web server -- command line startup and dynamic binding port number
1. Develop the command line and start the static web server with dynamic binding port number
Implementation steps:
- Get the command line parameters of the terminal executing the python program
- Judge the type of parameter and set the port number to be integer
- Add a port number parameter to the initialization method of the Web server class to bind the port number
2. Static Web server -- example code of dynamic binding port number for command line startup
import socket import threading import sys class HttpWebServer(object): # Initialize and create tcp server socket def __init__(self,port): # Create tcp server socket self.tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # ipv4 address Tcp transmission protocol # Set the port number reuse, and the port number will be released immediately after the program exits self.tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) # Binding port number self.tcp_server_socket.bind(("",port)) # The first parameter does not write anything, which represents the local ip address # Set the maximum number of listeners self.tcp_server_socket.listen(128) # Loop accept socket def start(self): while True: # Wait to receive the request from the client and return a tuple. Unpack the tuple to get a new socket (for message exchange) and a client's ip address new_socket, ip_port = self.tcp_server_socket.accept() # After the connection is established, the main thread creates a sub thread and calls the static method to process the client request sub_thread = threading.Thread(target=self.Handle, args=(new_socket,)) # Guard main thread sub_thread.setDaemon(True) # Start the child thread to execute the corresponding task sub_thread.start() # There is no self object in the method and the current class is not used to process the client request. It can be used as a static method @staticmethod def Handle(new_socket): # The code execution here indicates that the connection is successful recv_data = new_socket.recv(4096) # print(recv_data) # If the accepted data length is 0, close the socket if len(recv_data) == 0: new_socket.close() return # First decode the binary data recv_content = recv_data.decode("'utf-8") print(recv_content) # Divide the data into spaces request_list = recv_content.split(" ", maxsplit=2) # Split twice and return a tuple # Gets the path of the requested resource request_path = request_list[1] # The second item of the tuple is the requested resource path # print(request_path) # Judge whether the requested is the root directory. If it is the root directory, set the returned information if request_path == "/": request_path = "/index.html" # Find out if the file path exists # 1. os.path.exits os.path.exits("static/" + request_path) # 2. try-except try: with open("static" + request_path, "rb") as file: # The file object here represents the open file file_data = file.read() # Read data from file except Exception as e: # When the code is executed to this point, it indicates that the file is not requested to return 404 status information # Response line response_line = "HTTP/1.1 404 Not Found\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Read data from 404 pages with open("static/NotFound.html", "rb") as file: file_data = file.read() # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 else: # There is this path to send data # Using with open means that the file closing operation is not completed by the programmer, but by the system # The client is a browser, so the data needs to be encapsulated into the data in the format of data response message of http protocol # Response line response_line = "HTTP/1.1 200 OK\r\n" # Response header response_header = "Server: PWS/1.0\r\n" # Empty line # The html file above the response body should be placed in the response body, which is the data that the browser really needs to parse and display response_body = file_data response = (response_line + response_header + "\r\n").encode("utf-8") + response_body new_socket.send(response) # Coding required: utf-8 finally: # Close the socket on the server new_socket.close() def main(): # Get terminal command line parameters params = sys.argv if len(params) != 2: print("The format of the command executed is as follows: python3 xxx.py 9000") return # Judge whether the second parameter is a string composed of numbers if not params[1].isdigit(): print("The format of the command executed is as follows: python3 xxx.py 9000") return # When the code is executed here, it indicates that the number of command line parameters must be two, and the second parameter is a string composed of numbers port = int(params[1]) # Command line parameters are all in string form # Create web server web_server = HttpWebServer(port) # Start server web_server.start() # Returns the specified page data if __name__ == '__main__': main()