HTTPServer

HTTPServer

  1. 接收客户端请求
  2. 解析客户端请求
  3. 组织数据,形成HTTP respones
  4. 将数据发送给客户端

升级

  1. 采用多线程并发,接收多个客户端请求
  2. 基本的请求解析,根据请求返回相应的内容
  3. 除了可以请求静态网页,也可以请求简单的数据
  4. 将所有的功能封装在一个类中

技术点:

  1. socket tcp套接字
  2. http协议的请求响应格式
  3. 线程并发的创建方法
  4. 类的基本使用
# HTTPServer.py
'''
http server v2.0
1.多线程并发
2.可以请求简单的数据
3.能进行简单的数据解析
4.结构使用类进行封装
'''

from socket import *  # 套接字
from threading import Thread  # 线程
import sys  # 退出sys.exit('退出信息')
import traceback  # 打印具体异常信息


# httpserver 封装具体的服务器功能
class HTTPServer(object):
    def __init__(self, server_addr, static_dir):
        # 添加服务器对象属性
        self.server_addr = server_addr
        self.static_dir = static_dir
        self.ip = server_addr[0]
        self.port = server_addr[1]

        # 创建套接字
        self.create_socket()

    def create_socket(self):
        # 也为服务器对象属性
        self.sockfd = socket()
        self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.sockfd.bind(self.server_addr)


    # 进行监听,链接客户端,创建新的线程
    def serve_forever(self):
        # 进行监听
        self.sockfd.listen(5)
        print('Listen the port %d' % self.port)
        while True:
            try:
                connfd, addr = self.sockfd.accept()  # 连接客户端
            except KeyboardInterrupt:
                self.sockfd.close()
                sys.exit("服务器退出")
            except Exception:
                traceback.print_exc()  # 打印详细的错误信息
                continue
            # 创建新的线程处理请求
            clientThread = Thread(target=self.handleRequest, args=(connfd,))
            # 主进程退出子进程也随之退出
            clientThread.setDaemon(True)
            # 开启线程
            clientThread.start()

    # 客户端请求函数
    def handleRequest(self, connfd):
        # 接收客户端请求
        request = connfd.recv(4096)
        # print(request)
        # 解析请求内容
        requestHeaders = request.splitlines()
        # 获取请求行
        print(connfd.getpeername(), ':', requestHeaders[0])
        # 获取具体请求内容
        getRequest = str(requestHeaders[0]).split(' ')[1]

        if getRequest == '/' or getRequest[-5:] == '.html':
            self.get_html(connfd, getRequest)
        else:
            self.get_data(connfd, getRequest)
        connfd.close()

     # 获取网页  
    def get_html(self, connfd, getRequest):
        # 分析请求信息,进行归类
        if getRequest == '/':  # 获取主页信息
            # 路径加上文件名
            filename = self.static_dir + '/login.html'
        else:
            filename = self.static_dir + getRequest
        try:
            f = open(filename)
        except Exception:
            responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'  # 响应行
            responseHeaders += '\r\n'   # 空行
            responseBody = "Sorry, not found the page"  # 响应体
        else:
            responseHeaders = 'HTTP/1.1 200 OK\r\n'
            responseHeaders += '\r\n'  # 空行
            responseBody = f.read()  # 响应体为网页信息
        finally:
            response = responseHeaders + responseBody
            connfd.send(response.encode())  # 向客户段发送网页信息

    # 获取信息
    def get_data(self, connfd, getRequest):
        urls = ['/time', '/tedu', '/python']
        # 获取何种信息
        if getRequest in urls:
            responseHeaders = 'HTTP/1.1 200 OK\r\n'
            responseHeaders += '\r\n'
            if getRequest == '/time':
                import time
                responseBody = time.ctime()  # 打印当前时间
            elif getRequest == '/tedu':
                responseBody = 'Welcome to tedu'
            elif getRequest == '/python':
                responseBody = '人生苦短我用python'

        else:
            responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'
            responseHeaders += '\r\n'
            responseBody = "Sorry, not found the data"

        response = responseHeaders + responseBody
        connfd.send(response.encode())  # 向客户端发送网页信息


if __name__ == '__main__':
    # 服务器IP
    server_addr = ('0.0.0.0', 8000)

    # 我的静态页面存储目录
    static_dir = './static'

    # 生成类的对象
    httpd = HTTPServer(server_addr, static_dir)

    # 启动服务器,调用类内方法
    httpd.serve_forever()

你可能感兴趣的:(HTTPServer)