The 16th day of python learning notes

Article directory

1. http protocol

1.1 introduction to HTTP protocol

In the Web application, the server sends the Web page to the browser, in fact, it sends the HTML code of the Web page to the browser to display. The transport protocol between browser and server is HTTP, so:

  • Html is a kind of text used to define web pages. If you can understand HTML, you can write web pages;
  • HTTP is a protocol for transferring HTML over the network, which is used for communication between browser and server.

1.2 HTTP request

1.2.1 step 1

The browser first sends an HTTP request to the server, including:

Method: GET or POST, GET only requests resources, and POST will attach user data;

Path / full/url/path;

Domain name: specified by Host header: Host: www.sina.com

And other related headers;

In the case of POST, the request also includes a Body containing the user data

1.2.2 step 2

The server returns an HTTP response to the browser, including:

Response code: 200 indicates success, 3xx indicates redirection, 4xx indicates an error in the request sent by the client, and 5xx indicates an error in the processing of the server;

Response type: specified by content type;

And other related headers;

Usually, the HTTP response of the server will carry content, that is, there is a Body that contains the response content, and the HTML source code of the web page is in the Body.

1.2.3 step 3

If the browser needs to continue to request other resources from the server, such as pictures, it will send the HTTP request again, and repeat steps 1 and 2.

The HTTP protocol adopted by the Web adopts a very simple request response mode, which greatly simplifies the development. When we write a page, we only need to send the HTML in the HTTP request, without considering how to attach pictures, videos, etc. if the browser needs to request pictures and videos, it will send another HTTP request, so an HTTP request only processes one resource (in this case, it can be understood as a short connection in the TCP protocol, each link only gets one resource, If you need more than one, you need to establish more than one link)

The HTTP protocol also has strong scalability. Although the browser requests the homepage of http://www.sina.com, Sina can link resources of other servers in HTML, such as < img SRC = "http://i1.sinaimg.cn/home/2013/1008/u8455p30dt20131008135420. PNG" >, thus spreading the request pressure to each server, and one site can link to other sites, Numerous sites are linked to each other, forming the World Wide Web, or WWW for short.

1.3 HTTP format

Each HTTP request and response follows the same format. An HTTP consists of two parts: Header and Body, where Body is optional.

HTTP is a text protocol, so its format is very simple.

1.3.1 format of HTTP get request

    GET /path HTTP/1.1
    Header1: Value1
    Header2: Value2
    Header3: Value3

One per Header, line break is \ r\n.

1.3.2 format of HTTP post request

    POST /path HTTP/1.1
    Header1: Value1
    Header2: Value2
    Header3: Value3

    body data goes here...

When two consecutive headers are encountered, the Header part ends, and the following data is all Body.

1.3.3 format of HTTP response

    200 OK
    Header1: Value1
    Header2: Value2
    Header3: Value3

    body data goes here...

If the HTTP response contains a body, it is also delimited by \ r\n\r\n.

Please note again that the data type of the Body is determined by the content type header. If it is a web page, the Body is the text. If it is a picture, the Body is the binary data of the picture.

When there is content encoding, the Body data is compressed. The most common compression method is gzip. Therefore, when you see content encoding: gzip, you need to decompress the Body data first to get the real data. The purpose of compression is to reduce the size of the Body and speed up network transmission.

2. Web static server: display fixed pages

#coding=utf-8
import socket
def handle_client(client_socket):
    "Serving a client"
    recv_data = client_socket.recv(1024).decode("utf-8")
    request_header_lines = recv_data.splitlines()
    for line in request_header_lines:
        print(line)
    # Organize corresponding header
    response_headers = "HTTP/1.1 200 OK\r\n"  # 200 means this resource is found
    response_headers += "\r\n"  # Separate the body with an empty row
    # Organization content (body)
    response_body = "hello world"
    response = response_headers + response_body
    client_socket.send(response.encode("utf-8"))
    client_socket.close()
def main():
    "As the main control entry of the program"
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # Set that when the server close s first, that is, after the server waves four times, the resources can be released immediately, so that the 7788 port can be bound immediately the next time the program runs
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(("", 7788))
    server_socket.listen(128)
    while True:
        client_socket, client_addr = server_socket.accept()
        handle_client(client_socket)
if __name__ == "__main__":
    main()

3. Web static server: display the required page

#coding=utf-8
import socket
import re


def handle_client(client_socket):
    "Serving a client"
    recv_data = client_socket.recv(1024).decode('utf-8', errors="ignore")
    request_header_lines = recv_data.splitlines()
    for line in request_header_lines:
        print(line)

    http_request_line = request_header_lines[0]
    get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)
    print("file name is ===>%s" % get_file_name)  # for test

    # If you do not specify which page to visit. For example, index.html
    # GET / HTTP/1.1
    if get_file_name == "/":
        get_file_name = DOCUMENTS_ROOT + "/index.html"
    else:
        get_file_name = DOCUMENTS_ROOT + get_file_name

    print("file name is ===2>%s" % get_file_name) #for test

    try:
        f = open(get_file_name, "rb")
    except IOError:
        # 404 means there is no such page
        response_headers = "HTTP/1.1 404 not found\r\n"
        response_headers += "\r\n"
        response_body = "====sorry ,file not found===="
    else:
        response_headers = "HTTP/1.1 200 OK\r\n"
        response_headers += "\r\n"
        response_body = f.read()
        f.close()
    finally:
        # Since the header information is organized according to string, it cannot be combined with the data read by binary open file, so it is sent separately
        # Send the response header first
        client_socket.send(response_headers.encode('utf-8'))
        # Resend body
        client_socket.send(response_body)
        client_socket.close()


def main():
    "As the main control entry of the program"
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(("", 7788))
    server_socket.listen(128)
    while True:
        client_socket, clien_cAddr = server_socket.accept()
        handle_client(client_socket)


#Configure the server here
DOCUMENTS_ROOT = "./html"

if __name__ == "__main__":
    main()

4. Web static server - multi process

#coding=utf-8
import socket
import re
import multiprocessing


class WSGIServer(object):

    def __init__(self, server_address):
        # Create a tcp socket
        self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Allow the last bound port to be used immediately
        self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # binding
        self.listen_socket.bind(server_address)
        # Becomes passive and determines the length of the queue
        self.listen_socket.listen(128)

    def serve_forever(self):
        "cycle operation web Server, waiting for client link and serving client"
        while True:
            # Waiting for new clients to arrive
            client_socket, client_address = self.listen_socket.accept()
            print(client_address)  # for test
            new_process = multiprocessing.Process(target=self.handleRequest, args=(client_socket,))
            new_process.start()

            # Because the child process has copied the socket and other resources of the parent process, the parent process call close will not close their corresponding link
            client_socket.close()

    def handleRequest(self, client_socket):
        "Use a new process to serve a client"
        recv_data = client_socket.recv(1024).decode('utf-8')
        print(recv_data)
        requestHeaderLines = recv_data.splitlines()
        for line in requestHeaderLines:
            print(line)

        request_line = requestHeaderLines[0]
        get_file_name = re.match("[^/]+(/[^ ]*)", request_line).group(1)
        print("file name is ===>%s" % get_file_name) # for test

        if get_file_name == "/":
            get_file_name = DOCUMENTS_ROOT + "/index.html"
        else:
            get_file_name = DOCUMENTS_ROOT + get_file_name

        print("file name is ===2>%s" % get_file_name) # for test

        try:
            f = open(get_file_name, "rb")
        except IOError:
            response_header = "HTTP/1.1 404 not found\r\n"
            response_header += "\r\n"
            response_body = "====sorry ,file not found===="
        else:
            response_header = "HTTP/1.1 200 OK\r\n"
            response_header += "\r\n"
            response_body = f.read()
            f.close()
        finally:
            client_socket.send(response_header.encode('utf-8'))
            client_socket.send(response_body)
            client_socket.close()


# Set the port of the server
SERVER_ADDR = (HOST, PORT) = "", 8888
# Path to set server service static resources
DOCUMENTS_ROOT = "./html"


def main():
    httpd = WSGIServer(SERVER_ADDR)
    print("web Server: Serving HTTP on port %d ...\n" % PORT)
    httpd.serve_forever()

if __name__ == "__main__":
    main()

5. Web static server -- multithreading

#coding=utf-8
import socket
import re
import threading


class WSGIServer(object):

    def __init__(self, server_address):
        # Create a tcp socket
        self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Allow the last bound port to be used immediately
        self.listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # binding
        self.listen_socket.bind(server_address)
        # Becomes passive and determines the length of the queue
        self.listen_socket.listen(128)

    def serve_forever(self):
        "cycle operation web Server, waiting for client link and serving client"
        while True:
            # Waiting for new clients to arrive
            client_socket, client_address = self.listen_socket.accept()
            print(client_address)
            new_process = threading.Thread(target=self.handleRequest, args=(client_socket,))
            new_process.start()

            # Because the thread shares the same socket, the main thread cannot close, otherwise the sub thread can no longer use the socket
            # client_socket.close() 

    def handleRequest(self, client_socket):
        "Use a new process to serve a client"
        recv_data = client_socket.recv(1024).decode('utf-8')
        print(recv_data)
        requestHeaderLines = recv_data.splitlines()
        for line in requestHeaderLines:
            print(line)

        request_line = requestHeaderLines[0]
        get_file_name = re.match("[^/]+(/[^ ]*)", request_line).group(1)
        print("file name is ===>%s" % get_file_name) # for test

        if get_file_name == "/":
            get_file_name = DOCUMENTS_ROOT + "/index.html"
        else:
            get_file_name = DOCUMENTS_ROOT + get_file_name

        print("file name is ===2>%s" % get_file_name) # for test

        try:
            f = open(get_file_name, "rb")
        except IOError:
            response_header = "HTTP/1.1 404 not found\r\n"
            response_header += "\r\n"
            response_body = "====sorry ,file not found===="
        else:
            response_header = "HTTP/1.1 200 OK\r\n"
            response_header += "\r\n"
            response_body = f.read()
            f.close()
        finally:
            client_socket.send(response_header.encode('utf-8'))
            client_socket.send(response_body)
            client_socket.close()


# Set the port of the server
SERVER_ADDR = (HOST, PORT) = "", 8888
# Path to set server service static resources
DOCUMENTS_ROOT = "./html"


def main():
    httpd = WSGIServer(SERVER_ADDR)
    print("web Server: Serving HTTP on port %d ...\n" % PORT)
    httpd.serve_forever()

if __name__ == "__main__":
    main()

6. Web static server -- non blocking mode

6.1 single process non blocking model

#coding=utf-8
from socket import *
import time

# socket used to store all new links
g_socket_list = list()

def main():
    server_socket = socket(AF_INET, SOCK_STREAM)
    server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR  , 1)
    server_socket.bind(('', 7890))
    server_socket.listen(128)
    # Set socket to non blocking
    # When it is set to non blocking, if there is no client connect ion when accepting, then accept will
    # An exception is generated, so you need to try to handle it
    server_socket.setblocking(False)

    while True:

        # Used for testing
        time.sleep(0.5)

        try:
            newClientInfo = server_socket.accept()
        except Exception as result:
            pass
        else:
            print("A new client comes:%s" % str(newClientInfo))
            newClientInfo[0].setblocking(False)  # Set to non blocking
            g_socket_list.append(newClientInfo)

        for client_socket, client_addr in g_socket_list:
            try:
                recvData = client_socket.recv(1024)
                if recvData:
                    print('recv[%s]:%s' % (str(client_addr), recvData))
                else:
                    print('[%s]Client closed' % str(client_addr))
                    client_socket.close()
                    g_socket_list.remove((client_socket,client_addr))
            except Exception as result:
                pass

        print(g_socket_list)  # for test

if __name__ == '__main__':
    main()

6.2 web static server single process non blocking

import time
import socket
import sys
import re


class WSGIServer(object):
    """Define a WSGI Class of server"""

    def __init__(self, port, documents_root):

        # 1. Create socket
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. Bind local information
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind(("", port))
        # 3. Change to listening socket
        self.server_socket.listen(128)

        self.server_socket.setblocking(False)
        self.client_socket_list = list()

        self.documents_root = documents_root

    def run_forever(self):
        """Run server"""

        # Waiting for the other party's link
        while True:

            # time.sleep(0.5)  # for test

            try:
                new_socket, new_addr = self.server_socket.accept()
            except Exception as ret:
                print("-----1----", ret)  # for test
            else:
                new_socket.setblocking(False)
                self.client_socket_list.append(new_socket)

            for client_socket in self.client_socket_list:
                try:
                    request = client_socket.recv(1024).decode('utf-8')
                except Exception as ret:
                    print("------2----", ret)  # for test
                else:
                    if request:
                        self.deal_with_request(request, client_socket)
                    else:
                        client_socket.close()
                        self.client_socket_list.remove(client_socket)

            print(self.client_socket_list)


    def deal_with_request(self, request, client_socket):
        """For this browser server"""
        if not request:
            return

        request_lines = request.splitlines()
        for i, line in enumerate(request_lines):
            print(i, line)

        # Extract the requested file (index.html)
        # GET /a/b/c/d/e/index.html HTTP/1.1
        ret = re.match(r"([^/]*)([^ ]+)", request_lines[0])
        if ret:
            print("Regular extraction data:", ret.group(1))
            print("Regular extraction data:", ret.group(2))
            file_name = ret.group(2)
            if file_name == "/":
                file_name = "/index.html"


        # Read file data
        try:
            f = open(self.documents_root+file_name, "rb")
        except:
            response_body = "file not found, Please enter the correct url"
            response_header = "HTTP/1.1 404 not found\r\n"
            response_header += "Content-Type: text/html; charset=utf-8\r\n"
            response_header += "Content-Length: %d\r\n" % (len(response_body))
            response_header += "\r\n"

            # Return header to browser
            client_socket.send(response_header.encode('utf-8'))

            # Return body to browser
            client_socket.send(response_body.encode("utf-8"))
        else:
            content = f.read()
            f.close()

            response_body = content
            response_header = "HTTP/1.1 200 OK\r\n"
            response_header += "Content-Length: %d\r\n" % (len(response_body))
            response_header += "\r\n"

            # Return header to browser
            client_socket.send( response_header.encode('utf-8') + response_body)


# Path to set server service static resources
DOCUMENTS_ROOT = "./html"


def main():
    """control web Server as a whole"""
    # python3 xxxx.py 7890
    if len(sys.argv) == 2:
        port = sys.argv[1]
        if port.isdigit():
            port = int(port)
    else:
        print("The operation mode is as follows: python3 xxx.py 7890")
        return

    print("http Used by the server port:%s" % port)
    http_server = WSGIServer(port, DOCUMENTS_ROOT)
    http_server.run_forever()


if __name__ == "__main__":
    main()

7. Web static server - epoll

7.1 IO multiplexing

That is to say, select, poll, epoll. Some places also call this IO mode event driven IO.

The advantage of select/epoll is that a single process can handle IO of multiple network connections at the same time.

Its basic principle is select, poll, epoll. This function will continuously poll all the sockets it is responsible for. When a socket has data, it will notify the user process.

7.2 epoll simple model

import socket
import select

# Create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Set information that can be reused for binding
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)

# Bind native information
s.bind(("",7788))

# Become passive
s.listen(10)

# Create an epoll object
epoll = select.epoll()

# Test to print the file descriptor corresponding to the socket
# print(s.fileno())
# print(select.EPOLLIN|select.EPOLLET)

# Register events to epoll
# epoll.register(fd[, eventmask])
# Note that if the fd has already been registered, an exception will occur
# Add the created socket to epoll's event listening
epoll.register(s.fileno(), select.EPOLLIN|select.EPOLLET)

connections = {}
addresses = {}

# Cycle to wait for the arrival of the client or the other party to send data
while True:

    # Where epoll performs fd scanning -- if no timeout is specified, it is blocking waiting
    epoll_list = epoll.poll()

    # Judge the event
    for fd, events in epoll_list:

        # print fd
        # print events

        # If socket created by socket is activated
        if fd == s.fileno():
            new_socket, new_addr = s.accept()

            print('There are new clients coming%s' % str(new_addr))

            # Save conn and addr information respectively
            connections[new_socket.fileno()] = new_socket
            addresses[new_socket.fileno()] = new_addr

            # Register new socket's readable events with epoll
            epoll.register(new_socket.fileno(), select.EPOLLIN|select.EPOLLET)

        # If the client sends data
        elif events == select.EPOLLIN:
            # Receive from active fd
            recvData = connections[fd].recv(1024).decode("utf-8")

            if recvData:
                print('recv:%s' % recvData)
            else:
                # Remove the connection fd from epoll
                epoll.unregister(fd)

                # The server side actively closes the connection fd
                connections[fd].close()
                print("%s---offline---" % str(addresses[fd]))
                del connections[fd]
                del addresses[fd]

Explain

  • EPOLLIN (readable)
  • EPOLLOUT (writable)
  • EPOLLET (ET mode)

epoll operates on file descriptors in two modes: LT (level trigger) and ET (edge trigger). LT mode is the default mode. The difference between LT mode and et mode is as follows:

LT mode: when epoll detects a descriptor event and notifies the application of the event, the application can not immediately process the event. The next time epoll is called, it responds to the application again and notifies this event.

ET mode: when epoll detects a descriptor event and notifies the application of the event, the application must immediately handle the event. If not, the next time epoll is called, the application will not respond again and this event will be notified.

7.3 web static server epool

The following code supports http long connection, that is, content length is used

import socket
import time
import sys
import re
import select


class WSGIServer(object):
    """Define a WSGI Class of server"""

    def __init__(self, port, documents_root):

        # 1. Create socket
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. Bind local information
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind(("", port))
        # 3. Change to listening socket
        self.server_socket.listen(128)

        self.documents_root = documents_root

        # Create epoll object
        self.epoll = select.epoll()
        # Add tcp server socket to epoll for listening
        self.epoll.register(self.server_socket.fileno(), select.EPOLLIN|select.EPOLLET)

        # Create the socket corresponding to the added fd
        self.fd_socket = dict()

    def run_forever(self):
        """Run server"""

        # Waiting for the other party's link
        while True:
            # Where epoll performs fd scanning -- if no timeout is specified, it is blocking waiting
            epoll_list = self.epoll.poll()

            # Judge the event
            for fd, event in epoll_list:
                # If the server socket can receive data, it means that it can accept
                if fd == self.server_socket.fileno():
                    new_socket, new_addr = self.server_socket.accept()
                    # Register the readable events of connecting socket with epoll
                    self.epoll.register(new_socket.fileno(), select.EPOLLIN | select.EPOLLET)
                    # Record this information
                    self.fd_socket[new_socket.fileno()] = new_socket
                # Data received
                elif event == select.EPOLLIN:
                    request = self.fd_socket[fd].recv(1024).decode("utf-8")
                    if request:
                        self.deal_with_request(request, self.fd_socket[fd])
                    else:
                        # Information about unregistering clients in epoll
                        self.epoll.unregister(fd)
                        # Close client's file handle
                        self.fd_socket[fd].close()
                        # Delete information about closed clients in the dictionary
                        del self.fd_socket[fd]

    def deal_with_request(self, request, client_socket):
        """For this browser server"""

        if not request:
            return

        request_lines = request.splitlines()
        for i, line in enumerate(request_lines):
            print(i, line)

        # Extract the requested file (index.html)
        # GET /a/b/c/d/e/index.html HTTP/1.1
        ret = re.match(r"([^/]*)([^ ]+)", request_lines[0])
        if ret:
            print("Regular extraction data:", ret.group(1))
            print("Regular extraction data:", ret.group(2))
            file_name = ret.group(2)
            if file_name == "/":
                file_name = "/index.html"


        # Read file data
        try:
            f = open(self.documents_root+file_name, "rb")
        except:
            response_body = "file not found, Please enter the correct url"

            response_header = "HTTP/1.1 404 not found\r\n"
            response_header += "Content-Type: text/html; charset=utf-8\r\n"
            response_header += "Content-Length: %d\r\n" % len(response_body)
            response_header += "\r\n"

            # Return header to browser
            client_socket.send(response_header.encode('utf-8'))

            # Return body to browser
            client_socket.send(response_body.encode("utf-8"))
        else:
            content = f.read()
            f.close()

            response_body = content

            response_header = "HTTP/1.1 200 OK\r\n"
            response_header += "Content-Length: %d\r\n" % len(response_body)
            response_header += "\r\n"

            # Return data to browser
            client_socket.send(response_header.encode("utf-8")+response_body)


# Path to set server service static resources
DOCUMENTS_ROOT = "./html"


def main():
    """control web Server as a whole"""
    # python3 xxxx.py 7890
    if len(sys.argv) == 2:
        port = sys.argv[1]
        if port.isdigit():
            port = int(port)
    else:
        print("The operation mode is as follows: python3 xxx.py 7890")
        return

    print("http Used by the server port:%s" % port)
    http_server = WSGIServer(port, DOCUMENTS_ROOT)
    http_server.run_forever()


if __name__ == "__main__":
    main()

Small summary

I/O multiplexing features:

Through a mechanism, a process can wait for multiple file descriptors at the same time, and any of these file descriptors (socket descriptors) enter the read ready state, and the epoll() function can return. Therefore, IO multiplexing does not have concurrent function in essence, because there is only one process or thread working at any time. The reason why it can improve efficiency is that select\epoll puts the incoming socket in their 'monitoring' list. When any socket has readable and writable data to be processed immediately, if select\epoll detects many sockets at the same time, As soon as there is any movement, it will be returned to the process for processing, which is always more efficient than socket by socket, blocking and waiting.

Of course, it can also be multi-threaded / multi-process mode. A connection can start a process / thread processing, so the memory consumed and the process switching page will consume more system resources. So we can combine IO multiplexing and multiprocess / multithreading to achieve high-performance concurrency. IO multiplexing is responsible for improving the notification efficiency of receiving socket. After receiving the request, it is handed over to the process pool / thread pool to process the logic.

Reference material

8 web static server - gevent version

from gevent import monkey
import gevent
import socket
import sys
import re

monkey.patch_all()


class WSGIServer(object):
    """Define a WSGI Class of server"""

    def __init__(self, port, documents_root):

        # 1. Create socket
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. Bind local information
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind(("", port))
        # 3. Change to listening socket
        self.server_socket.listen(128)

        self.documents_root = documents_root

    def run_forever(self):
        """Run server"""

        # Waiting for the other party's link
        while True:
            new_socket, new_addr = self.server_socket.accept()
            gevent.spawn(self.deal_with_request, new_socket)  # Create a collaboration to run it

    def deal_with_request(self, client_socket):
        """For this browser server"""
        while True:
            # receive data
            request = client_socket.recv(1024).decode('utf-8')
            # print(gevent.getcurrent())
            # print(request)

            # When the browser receives the data, it will automatically call close to close, so when it closes, the web will also close the socket
            if not request:
                new_socket.close()
                break

            request_lines = request.splitlines()
            for i, line in enumerate(request_lines):
                print(i, line)

            # Extract the requested file (index.html)
            # GET /a/b/c/d/e/index.html HTTP/1.1
            ret = re.match(r"([^/]*)([^ ]+)", request_lines[0])
            if ret:
                print("Regular extraction data:", ret.group(1))
                print("Regular extraction data:", ret.group(2))
                file_name = ret.group(2)
                if file_name == "/":
                    file_name = "/index.html"

            file_path_name = self.documents_root + file_name
            try:
                f = open(file_path_name, "rb")
            except:
                # If you can't open this file, it means that you don't have this resource. If you don't have a resource, you need to tell the browser some data
                # 404
                response_body = "No documents you need......".encode("utf-8")

                response_headers = "HTTP/1.1 404 not found\r\n"
                response_headers += "Content-Type:text/html;charset=utf-8\r\n"
                response_headers += "Content-Length:%d\r\n" % len(response_body)
                response_headers += "\r\n"

                send_data = response_headers.encode("utf-8") + response_body

                client_socket.send(send_data)

            else:
                content = f.read()
                f.close()

                # body information of response
                response_body = content
                # Response header information
                response_headers = "HTTP/1.1 200 OK\r\n"
                response_headers += "Content-Type:text/html;charset=utf-8\r\n"
                response_headers += "Content-Length:%d\r\n" % len(response_body)
                response_headers += "\r\n"
                send_data = response_headers.encode("utf-8") + response_body
                client_socket.send(send_data)

# Path to set server service static resources
DOCUMENTS_ROOT = "./html"

def main():
    """control web Server as a whole"""
    # python3 xxxx.py 7890
    if len(sys.argv) == 2:
        port = sys.argv[1]
        if port.isdigit():
            port = int(port)
    else:
        print("The operation mode is as follows: python3 xxx.py 7890")
        return

    print("http Used by the server port:%s" % port)
    http_server = WSGIServer(port, DOCUMENTS_ROOT")
    http_server.run_forever()


if __name__ == "__main__":
    main()
Published 31 original articles, won praise 25, visited 5487
Private letter follow

Tags: socket Web Server network encoding

Posted on Thu, 06 Feb 2020 01:01:55 -0500 by s1m0n