用python写的简单的http文件服务器demo

import socket
import os
import re
import time
from multiprocessing import Process

class CHttpServer(object):
    """Httpserver服务端类"""
    def __init__(self):
        self.m_serverSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.m_serverSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.m_buf_size = 8 * 1024 * 1024
    def start(self):
        self.m_serverSocket.listen(128)
        while(True):
            m_clientSocket,m_clientAddr = self.m_serverSocket.accept()
            m_clientSocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
            print("创建的socket是", end="")
            print(m_clientSocket)
            print('[%s,%s]用户连接上了服务器' % m_clientAddr)
            handle_client_process = Process(target = self.handle_client,args=(m_clientSocket,))
            handle_client_process.start()
            m_clientSocket.close()
    #数据处理进程
    def handle_client(self,clientSocket):
        '''
        处理客户请求操作
        '''
        #获取客户请求数据
        print("进程:", end="")
        print(os.getpid())
        request_data = clientSocket.recv(2048)
        print('接收到的数据:%s' % request_data)
        request_lines=request_data.splitlines()
        bytes_start = ""
        bytes_end = ""
        req_method = str(request_lines[0], encoding="utf8").split("/")[0].strip()
        print(req_method)
        print(req_method)
        req_data_byte_status = False
        if req_method == "GET":
            for line in request_lines:
                print(str(line))
                if "Range" in str(line, encoding="utf8") or "range" in str(line, encoding="utf8") :
                    bytes_start, bytes_end = self.parse_range(str(line, encoding="utf8"))
                    req_data_byte_status = True

            file_size = os.path.getsize("test.mp4")

            if req_data_byte_status:
                if bytes_end == "" and bytes_start == "0" : # 说明全部读取
                    response_start_line = "HTTP/1.1 206 Partial Content\r\n"
                    response_headers = "Server: My server\r\n"
                    response_headers = response_headers + "Accept-Ranges: bytes\r\n"
                    # response_headers = response_headers + "Content-Length: {}\r\n".format(str(file_size))
                    response_headers = response_headers + "Content-Length: {}\r\n".format(str(file_size))
                    response_headers = response_headers + "Content-Range: bytes 0-{}/{}\r\n".format(str(file_size-1), file_size)
                    response_headers = response_headers + "Content-Type: video/mp4\r\n"
                    response = response_start_line + response_headers + "\r\n"
                    clientSocket.send(bytes(response, "utf8"))  # 到底是不是这种模式
                    videofile = open("test.mp4", "rb")
                    while True:
                        video_bytes = videofile.read(self.m_buf_size)
                        if not video_bytes: #文件读取完毕
                            break
                        print("socket status :", end="")
                        print(clientSocket)
                        try:
                            clientSocket.send(video_bytes)
                        except Exception as e:
                            print(e)
                            break

                    videofile.close()
                    clientSocket.close()  # 这里如果不 close, 这个子进程结束运行后
                else:

                    bytes_start = int(bytes_start)
                    if bytes_start >= file_size:
                        response_body =  "<html><head><title>416 Requested Range Not Satisfiable</title></head><body><center><h1>416 Requested Range Not Satisfiable</h1></center><hr><center>nginx/1.18.0</center></body></html>"
                        response_start_line = "HTTP/1.1 416 Requested Range Not Satisfiable\r\n"
                        response_headers = "Server: My server\r\n"
                        response_headers = response_headers + "Accept-Ranges: bytes\r\n"
                        response_headers = response_headers + "Content-Length: {}\r\n".format(len(response_body))
                        response_headers = response_headers + "Content-Type: text/html\r\n"
                        response_headers = response_headers + "Content-Range: bytes */{}\r\n".format(str(file_size))
                        response = response_start_line + response_headers + "\r\n"
                        response = response + response_body
                        clientSocket.send(bytes(response, "utf8"))
                        clientSocket.close()
                    else:
                        if bytes_end != "" :
                            bytes_end = int(bytes_end)
                        else:
                            bytes_end = file_size - 1

                        need_get_size = bytes_end - bytes_start + 1
                        total_get_size = 0

                        response_start_line = "HTTP/1.1 206 Partial Content\r\n"
                        response_headers = "Server: My server\r\n"
                        response_headers = response_headers + "Accept-Ranges: bytes\r\n"
                        response_headers = response_headers + "Content-Length: {}\r\n".format(
                            str(bytes_end - bytes_start + 1))
                        response_headers = response_headers + "Content-Type: video/mp4\r\n"
                        response_headers = response_headers + "Content-Range: bytes {}-{}/{}\r\n".format(str(bytes_start), str(bytes_end), file_size)
                        response = response_start_line + response_headers + "\r\n"
                        print(response)
                        clientSocket.send(bytes(response, "utf8"))
                        videofile = open("test.mp4", "rb")
                        videofile.seek(bytes_start, 0)
                        while True:
                            if self.m_buf_size < need_get_size:
                                video_bytes = videofile.read(self.m_buf_size)
                                if not video_bytes: # 说明文件读取完毕
                                    break
                                print("-"*25)
                                print(need_get_size)
                                try:
                                    clientSocket.send(video_bytes)
                                except Exception as e:
                                    print(e)
                                    break
                                need_get_size = need_get_size - len(video_bytes)
                            else:
                                video_bytes = videofile.read(need_get_size)
                                if not video_bytes:  # 说明文件读取完毕
                                    break
                                try:
                                    clientSocket.send(video_bytes)
                                except Exception as e:
                                    print(e)
                                    break
                                break

                        videofile.close()
                        clientSocket.close() # 这里如果不 close, 这个子进程结束运行后, socket会不会自己close掉
            else:
                # response_start_line = "HTTP/1.1 206 Partial Content\r\n" QT 播放器 在这里会失败
                response_start_line = "HTTP/1.1 200 ok\r\n"
                response_headers = "Server: My server\r\n"
                response_headers = response_headers + "Accept-Ranges: bytes\r\n"
                response_headers = response_headers + "Content-Length: {}\r\n".format(str(file_size))
                response_headers = response_headers + "Content-Range: bytes 0-{}/{}\r\n".format(str(file_size - 1),
                                                                                                file_size)
                response_headers = response_headers + "Content-Type: video/mp4\r\n"
                response = response_start_line + response_headers + "\r\n"
                clientSocket.send(bytes(response, "utf8"))  # 到底是不是这种模式
                print(response)
                videofile = open("test.mp4", "rb")
                while True:
                    video_bytes = videofile.read(self.m_buf_size)
                    if not video_bytes:  # 文件读取完毕
                        break
                    print("socket status :", end="")
                    print(clientSocket)
                    try:
                        clientSocket.send(video_bytes)
                    except Exception as e:
                        print(e)
                        break

                videofile.close()
                clientSocket.close()


    def parse_range(self, part_header):
        '''
        解析出请求中的 range start end
        :return: start end
        '''
        print(part_header)
        temp = part_header.split(":")
        temp = temp[1].split("=")
        temp = temp[1].split("-")
        start = temp[0]
        end = ""
        if len(temp) == 2:
            end = temp[1]
        return start, end

    def get_file_info(self, url):
        pass
    #绑定端口
    def bind(self,port):
        self.m_serverSocket.bind(('',port))
    def parseline(self,strcon):
        """解析字符串"""
        pass


def main():
    http_server = CHttpServer()
    http_server.bind(8000)
    http_server.start()

if __name__ == "__main__":
    main()

# http://127.0.0.1:8000