Python-Level2-day17:http请求与响应,web 服务项目实现,高并发技术探讨

4. web服务

4.1 HTTP协议

4.1.1 协议概述

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

  • 特点

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

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

    • 有丰富的请求类型

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

4.1.2 网页访问流程

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

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

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

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

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

 

 

4.1.2 HTTP请求

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

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

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

    GET : 获取网络资源
    POST :提交一定的信息,得到反馈
    HEAD : 只获取网络资源的响应头
    PUT : 更新服务器资源
    DELETE : 删除服务器资源
  • 请求头:对请求的进一步解释和描述(例如什么时间用什么浏览器发给服务器的)

    eg.Accept-Encoding: gzip   一行行键值对构成
  • 空行

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

 

 

4.1.3 HTTP响应

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

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

响应码 :

    1xx  提示信息,表示请求被接收
    2xx  响应成功
    3xx  响应需要进一步操作,即二次处理重定向
    4xx  客户端错误
    5xx  服务器错误
  • 响应头:对响应内容的描述 ----详细解释给你的响应是什么格式,大小等信息

    eg.Content-Type: text/html ---以网页格式解析
  • 空行

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

 

 

"""
http 请求和响应
"""
from socket import *
​
# 创建tcp套接字
sock = socket()
sock.bind(("0.0.0.0", 8888))
sock.listen(5)
​
# 等待浏览器连接
connfd, addr = sock.accept()
print("Connect from", addr)
​
# 接收HTTP请求
request = connfd.recv(1024)
print(request.decode())
​
# 组织响应格式
response = """HTTP/1.1 200 OK
Content-Type:text/html
​
Hello World
"""
connfd.send(response.encode())  # 发送响应
​
connfd.close()
sock.close()
​
"""
练习: 根据所学http协议完成
通过浏览器访问服务端,请求根 则会
显示一张图片在浏览器上 ,图片自选
​
Content-Type:image/jpeg
"""
from socket import *
​
​
def get_response(filename):
    response = "HTTP/1.1 200 OK\r\n"
    response += "Content-Type:image/jpeg\r\n"
    response += "\r\n"
    with open(filename, 'rb') as file:
        response = response.encode() + file.read()
    return response  # 字节串
​
​
def main():
    sock = socket()
    sock.bind(("0.0.0.0", 8000))
    sock.listen(5)
​
    while True:#浏览器可以多个页面循环访问
        connfd, addr = sock.accept()
        print("Connect from", addr)
        # 接收请求
        request = connfd.recv(1024)
        print(request.decode())
        response = get_response("yaya.jpeg")#前端工程师提供图像信息
        connfd.send(response)  # 字节串
​
​
if __name__ == '__main__':
    main()
​

4.2 web 服务项目实现

  1. 主要功能 : 【1】 接收客户端(浏览器)请求

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

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

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

  2. 主要特点 :

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

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

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

"""
web sever 服务
"""
from socket import *
from select import select
import os
​
​
# 具体处理http请求
class Handle:
    def __init__(self, html):
        self.html = html
​
    def _response(self, status, filename):
        response = "HTTP/1.1 %s\r\n" % status
        response += "Content-Type:text/html\r\n"
        response += "\r\n"
        with open(filename, 'rb') as file:
            response = response.encode() + file.read()
        return response
​
    def _send_response(self, connfd, info):
        # 请求的是 首页 还是 其他网页
        if info == '/':
            filename = self.html + "/index.html"
        else:
            filename = self.html + info
​
        # 判断是否存在 True / False
        if os.path.exists(filename):
            data = self._response("200 OK", filename)
        else:
            data = self._response("404 Not Found", self.html + "/404.html")
        connfd.send(data)  # 发送响应
​
    def handle(self, connfd):
        # 接收HTTP请求
        request = connfd.recv(1024).decode()
        if not request:
            return
        # 获取请求内容
        info = request.split(" ")[1]
        print('请求内容:', info)
        # 组织响应并发送
        self._send_response(connfd, info)
​
​
class WebServer:
    # 实例化对象过程中做好准备工作
    def __init__(self, host='', port=0, html=None):
        self.host = host
        self.port = port
        self.address = (host, port)
        self.html = html  # 用户提供的网页
        self.rlist = []
        self.handle = Handle(html)
        self.sock = self._create_socket()
​
    # 创建套接字
    def _create_socket(self):
        sock = socket()
        sock.bind(self.address)
        sock.setblocking(False)  # 非阻塞
        return sock
​
    # 连接浏览器
    def _connect(self):
        connfd, addr = self.sock.accept()
        connfd.setblocking(False)
        self.rlist.append(connfd)  # 增加关注
​
    # start启动函数过程中 搭建服务  IO并发模型
    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, [], [])
            for r in rs:
                if r is self.sock:
                    self._connect()  # 处理连接
                else:
                    try:
                        self.handle.handle(r)  # 处理http请求
                    except:
                        pass
                    self.rlist.remove(r)  # 短连接场景,处理完即关闭
                    r.close()
​
​
if __name__ == '__main__':
    # 先想一下怎么用
    # 什么需要用户决定: 服务器地址  内容
    httpd = WebServer(host="0.0.0.0", port=8888,
                      html="./static")
    httpd.start()  # 启动服务
​

5. 高并发技术探讨

5.1 高并发问题

  • 衡量高并发的关键指标

    • 响应时间(Response Time) : 接收请求后处理的时间

    • 同时在线用户数量:同时连接服务器的用户的数量

    • 每秒查询率QPS(Query Per Second): 每秒接收请求的次数

    • 每秒事务处理量TPS(Transaction Per Second):每秒处理请求的次数(包含接收,处理,响应)

    • 吞吐量(Throughput): 响应时间+QPS+同时在线用户数量

  • 多大的并发量算是高并发

    • 没有最高,只要更高

      比如在一个小公司可能QPS2000+就不错了,在一个需要频繁访问的门户网站可能要达到QPS5W+

    • C10K问题

      早先服务器都是单纯基于进程/线程模型的,新到来一个TCP连接,就需要分配1个进程(或者线程)。而进程占用操作系统资源多,一台机器无法创建很多进程。如果是C10K就要创建1万个进程,那么单机而言操作系统是无法承受的,这就是著名的C10k问题。创建的进程线程多了,数据拷贝频繁, 进程/线程切换消耗大, 导致操作系统崩溃,这就是C10K问题的本质!

5.2 更高并发的实现

为了解决C10K问题,现在高并发的实现已经是一个更加综合的架构艺术。涉及到进程线程编程,IO处理,数据库处理,缓存,队列,负载均衡等等,这些我们在后面的阶段还会学习。此外还有硬件的设计,服务器集群的部署,服务器负载,网络流量的处理等。

 

 

实际工作中,应对更庞大的任务场景,网络并发模型的使用有时也并不单一。比如多进程网络并发中每个进程再开辟线程,或者在每个进程中也可以使用多路复用的IO处理方法。

 

前情回顾

1. IO多路复用

   利用系统内核的IO监控功能 ,哪个IO就绪就处理哪个IO
   对象,形成多个IO可以 "同时" 处理多个IO

   IO多路是单进程,资源占用少,但是只能处理简单的IO操作

2. select   epoll

   select: 平台支持好,但是同时监控IO数量有限,效率没有
           epoll高

   epoll : 效率高,支持同时监控IO数量多,但是只用于Linux

3. 使用IO多路复用实现网络并发


4. HTTP 协议

   应用层   tcp传输    简单方便   请求类型多

   HTTP协议使用: 传输数据  访问网站
                网页访问流程


练习: 根据所学http协议完成
通过浏览器访问服务端,请求根 则会
显示一张图片在浏览器上 ,图片自选

Content-Type:image/jpeg

webserver 模块

需求分析
    接收客户端(浏览器)请求
    解析客户端发送的请求
    根据请求组织数据内容
    将数据内容形成http响应格式返回给浏览器

技术 :  IO多路复用并发网络 : select
       TCP

模块封装 :  类
协议 : HTTP协议

类接口设计 :

   socket : 生成对象,使用对象灵活的调用各种方法
            组合,就会产生不同的功能效果

   Process : 生成对象,调用方法启动功能 (如果多
   调用方法也是为主体功能服务的),能为用户决定就帮他决定
   不能替用户决定需要用户传参

核心编程

1. 网络编程

   网络基础知识:
      1. TCP/IP模型和OSI七层模型
      2. 三次握手和四次挥手过程
      3. tcp和udp的区别
      4. http协议的特点和请求响应格式

   socket 模块
      tcp套接字编程 (重点)

      udp套接字编程 (重点)


2. 进程和线程

   基础概念
     1. 进程与线程的特点和区别
     2. 理解什么是进程和进程状态

   多进程  (包括自定义进程类)  重点,难点
      multiprocessing

   多线程  (包括同步互斥方法)  重点
      threading
      GIL


3. IO模型

   阻塞IO

   非阻塞IO

   IO多路复用 (重点,难点)
      select
      epoll


4. 网络并发模型

   多进程多线程并发 (重点)

   IO多路复用并发 (重点)

5. 综合代码
    学生管理系统 :
       文件  正则   函数编程

    群聊聊天室 :
       udp   多进程  函数编程
       通信协议请求  "总分结构"

    ftp文件服务器
       tcp   多线程并发模型   面向对象
       通信协议响应   请求应答的模式

    webserver
       tcp   IO多路复用并发模型  设计类接口
       类的设计思路

<核心编程 第三版>
<图解TCP/IP>
<图解HTTP>


作业: 1. webserver自己写一下
     2.  github.com
         gitee.com


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dpq666dpq666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值