• web服务webserver


    1.HTTP协议

      用途: 网页获取,数据的传输

      特点:   

    • 应用层协议,使用tcp进行数据传输

    • 简单,灵活,很多语言都有HTTP专门接口

    • 无状态,数据传输过程中不记录传输内容

    • 有丰富了请求类型

    • 可以传输的数据类型众多

    网页访问流程

      客户端(浏览器)通过TCP传输,发送http请求给服务端

      服务端接收到http请求后进行解析

      服务端处理请求内容,组织响应内容

      服务端将响应内容以http响应格式发送给浏览器

      浏览器接收到响应内容,解析展示

    HTTP请求

      请求行:具体的请求类别和请求内容

        GET         /        HTTP/1.1
        请求类别   请求内容     协议版本

        请求类别:每个请求类别表示要做不同的事情

            GET : 获取网络资源
            POST :提交一定的信息,得到反馈
            HEAD : 只获取网络资源的响应头
            PUT : 更新服务器资源
            DELETE : 删除服务器资源

      请求头:对请求的进一步解释和描述

    Accept-Encoding: gzip

      空行

      请求体:请求参数或者提交内容

    HTTP响应

      响应行:反馈基本的响应情况

    HTTP/1.1     200       OK
    版本信息    响应码   附加信息

      响应码:

    1xx  提示信息,表示请求被接收
    2xx  响应成功
    3xx  响应需要进一步操作,重定向
    4xx  客户端错误
    5xx  服务器错误

      响应头:对响应内容的描述

    Content-Type: text/html
    Content-Length:109
    

      空行

      响应体:响应的主体内容信息

    练习:主要功能 :

      【1】 接收客户端(浏览器)请求

      【2】 解析客户端发送的请求

      【3】 根据请求组织数据内容

      【4】 将数据内容形成http响应格式返回给浏览器

    特点 :

      【1】 采用IO并发,可以满足多个客户端同时发起请求情况

      【2】 通过类接口形式进行功能封装

      【3】 做基本的请求解析,根据具体请求返回具体内容,同时可以满足客户端的网页效果加载

    需求分析

    技术点 : HTTP协议
             IO多路复用的并发网络模型

    功能划分和封装: 类封装

    协议 : http协议

    逻辑实现步骤


    功能性类 / 类接口

      socket()
         实例化对象 --> 不同的对象做些属性设置-->通信

      Process()/Thread()
         实例化对象 --> 绑定事件 --> 启动进程线程服务

      核心功能是干什么:网页分享
      使用流程:实例化对象 -> 启动服务
      传参 : 服务器地址  网页文件

      用户自己决定的是: 服务器地址  网页文件

    逻辑步骤:
       tcp套接字
       搭建IO多路复用的并发模型
       接收客户端(浏览器)请求
       解析客户端发送的请求
       根据请求组织数据内容
       将数据内容形成http响应格式返回给浏览器

    """
    web server 程序
    
    完成一个类,提供给使用者
    可以通过这个类快速搭建服务
    完成网页展示
    """
    from socket import *
    from select import select
    import re
    
    # 封装所有web后端功能
    class WebServer:
        def __init__(self, host="0.0.0.0", port=80, html=None):
            self.host = host
            self.port = port
            self.html = html
            self.rlist = []
            self.wlist = []
            self.xlist = []
            self.create_socket()
            self.bind()
    
        # 创建设置套接字
        def create_socket(self):
            self.sock = socket()
            self.sock.setblocking(False)
    
        # 绑定地址
        def bind(self):
            self.address = (self.host, self.port)
            self.sock.bind(self.address)
    
        # 启动整个服务
        def start(self):
            self.sock.listen(5)
            print("Listen the port %d" % self.port)
            # 先监控监听套接字
            self.rlist.append(self.sock)
            # 循环监控IO对象
            while True:
                rs, ws, xs = select(self.rlist, self.wlist, self.xlist)
                # 处理就绪的IO
                for r in rs:
                    # 有客户端连接
                    if r is self.sock:
                        connfd, addr = r.accept()
                        print("Connect from", addr)
                        # 将客户端连接套接字也监控起来
                        connfd.setblocking(False)
                        self.rlist.append(connfd)
                    else:
                        # 处理浏览器端发的请求
                        try:
                            self.handle(r)
                        except:
                            pass
                        self.rlist.remove(r)
                        r.close()
    
        # 处理客户端请求
        def handle(self, connfd):
            # http请求
            request = connfd.recv(1024 * 10).decode()
            # 使用正则匹配请求内容
            pattern = r"[A-Z]+s+(?P<info>/S*)"
            result = re.match(pattern, request)
            if request:
                # 提取请求内容
                info = result.group("info")
                print("请求内容:",info)
                self.send_html(connfd,info)
    
        # 发送响应
        def send_html(self,connfd,info):
            # 对info分情况
            if info == "/":
                filename = self.html + "/index.html"
            else:
                filename = self.html + info
    
            # 打开判断文件是否存在
            try:
                file = open(filename,"rb")
            except:
                # 请求的网页不存在
                response = "HTTP/1.1 404 Not Found
    "
                response += "Content-Type:text/html
    "
                response += "
    "
                with open(self.html+"/404.html") as file:
                    response += file.read()
                response = response.encode()
            else:
                # 请求的网页存在
                data = file.read() # 字节串
                response = "HTTP/1.1 200 OK
    "
                response += "Content-Type:text/html
    "
                response += "Content-Length:%d
    "%len(data)
                response += "
    "
                response = response.encode() + data
                file.close()
            finally:
                connfd.send(response)
    
    
    
    if __name__ == '__main__':
        # 需要用户决定: 地址  网页
        httpd = WebServer(host="0.0.0.0",
                          port=8000,
                          html="./static")
        # 启动服务
        httpd.start()

     

     

     

    Live what we love, do what we do, follow the heart, and do not hesitate.
  • 相关阅读:
    使用NPOI将TABLE内容导出到EXCEL
    如何判断一个指定的经纬度点是否落在一个多边形区域内?
    SQL随记(三)
    SQL随记(二)
    SQL随记(一)
    微信开发(1)
    关于面试经验的总结
    动态代理是什么
    集合的遍历以及在Spring中的注入
    向服务器发送邮件(四)
  • 原文地址:https://www.cnblogs.com/failan/p/13880319.html
Copyright © 2020-2023  润新知