HTTP协议
2021-05-05 14:28
                         标签:ons   等等   通过命令   line   内容   传输层   红点   选择   嵌套    HTTP协议: 模拟简单浏览器进行网络通信: web服务器: web服务器返回固定页面: web服务器-面向对象实现: 协程实现多任务: web服务器-命令行参数控制内部绑定的端口: HTTP协议 标签:ons   等等   通过命令   line   内容   传输层   红点   选择   嵌套    原文地址:https://www.cnblogs.com/huaibin/p/12107300.html"""
http服务器本质也是tcp服务器.
浏览器  --> (通过HTTP协议 格式) HTTP服务器,也可看作是TCP服务器
格式:就是http协议
域名就是一串字符串.域名的本质还是IP.
域名找DNS去解析域名,转换成对应的IP.(类似找电话本的过程,由电话本里面的名字找到对应的电话号码,这里名字就是域名,电话号码就是IP地址)
域名解析:域名转换成IP地址
domain name service
DNS:1.> 建立连接 2.> 发起请求 3.> 回复响应
DHCP:动态主机配置协议 dynamic host configuration protocol .给局域网中的计算机自动分配IP
"""
"""
url:就是网址,分为下面三部分
	1.协议部分
	2.域名部分
	3.资源路径部分   --> 就是用户想要访问的资源在服务器的哪个位置的哪个文件
	
HTTP协议: 超文本传输协议 就是用来传输网页的数据.制作者:蒂姆.博纳斯.李 为了方便科学家展示研究成果
而开发的协议.就可以实现跨网络的数据传输.
目前使用的就是http/1.1版本
HTTP作用:浏览器-服务器之间传输网页数据资源
HTTP协议:就是tcp协议加上一些格式
网路传输模型:
	应用层 http/https ftp/sftp:加了s的就是加密了
	传输层 tcp/udp 比较底层了  端口是传输层使用的
	网络层 ip  更加底层了
	网络接口层  最底层
	
寄快递--> 应用层  任务/目标
快递公司--> 顺丰 邮政 选择哪一家快递公司提供服务  传输层  选择哪一种传输协议
物流中转站--> 网络层 转发 选择路径 根据目的ip选择路径 转发出去 就是根据目的地址选择走哪条路径 然后发出去
运输工具--> 轮船,飞机,火车,汽车 网络接口层,就看底层 提供了什么工具了  运输过程选择什么工具进行运输
路由器是工作在网络层的/和ip打交道 将数据包根据ip进行转发 
交换机是工作在传输层的
HTTP协议的工作模式:一次请求
# 0.创建socket
# 1.输入网址 域名解析 获取服务器ip
# 2.和服务器建立连接
# 3.发送 请求报文
# 4.接收 响应报文
# \r\n记得一定要带,否则会出错
import socket
# 创建socket
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
tcp_socket.connect((‘www.jd.com‘, 80))
# 请求行
request_line = ‘GET / HTTP/1.1\r\n‘
# 请求头
request_header = ‘User-Agent:%s\r\n‘ % (
    ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36‘)
# 拼接请求数据
request_data = request_line + request_header + ‘\r\n‘
# 转成bytes字节类型进行发送
tcp_socket.send(request_data.encode())
# 返回服务器回送的数据
response_data = tcp_socket.recv(4096)
# 输出
print(response_data.decode())
"""
流程: Nginx  脑海中建立一条生产线
PWS1.0目的:在用户每次访问的时候,都返回一个固定的数据,例如Hello World
1.>接收请求报文
2.>解析请求报文-得到用户需求
3.>根据用户的需求找到对应的资源
4.>资源打包到HTTP响应报文
5.>发送响应报文给浏览器
最开始肯定是最简单的,一步一步的加多,慢慢地才会出来
PWS1.0:Python Web Server 1.0
"""
import socket
def main():
    # 1. 创建tcp服务器的socket  设置选项 绑定 监听
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind((‘‘, 8887))  # 这里绑定的是服务器的固定端口,目的是让客户端能连接到了我的机器上面之后,可以找到我的这个程序
    server_socket.listen(128)
    while True:
        # 2.接受用户连接,从这里开始才是需要不断的进行,才使用死循环
        client_socket, client_addr = server_socket.accept()
        print(‘接受到%s的连接请求‘ % str(client_addr))
        # 3.接收用户请求报文
        request_data = client_socket.recv(4096)
        print(type(request_data))  # 
 标题加粗的效果
        #               响应行               响应头/可以是0个  空行 响应体数据   这四个 只有响应头可以省略,其他的都不可以省略
        response_data = ‘HTTP/1.1 200 OK\r\nServer:PWS1.0\r\n\r\n‘ + ‘Hello World
‘
        client_socket.send(response_data.encode())
        # 5.一次请求/响应 就关闭连接  --> 短连接
        client_socket.close()
if __name__ == ‘__main__‘:
    main()"""
PWS2.0目的:在用户每次访问的时候,都会返回一个固定的页面,比如index.html
1.>接收请求报文
2.>解析请求报文-得到用户需求
3.>根据用户的需求找到对应的资源
4.>资源打包到HTTP响应报文
最开始肯定是最简单的,一步一步的加多,慢慢地才会出来
PWS2.0:Python Web Server 2.0
"""
import socket
def main():
    # 1. 创建tcp服务器的socket  设置选项 绑定 监听
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind((‘‘, 8888))  # 这里绑定的是服务器的固定端口,目的是让客户端能连接到了我的机器上面之后,可以找到我的这个程序
    server_socket.listen(128)
    while True:
        # 2.接受用户连接
        client_socket, client_addr = server_socket.accept()
        print(‘接受到%s的连接请求‘ % str(client_addr))
        # 3.接收用户请求报文
        request_data = client_socket.recv(4096)
        print(request_data)
        # 4.返回固定的文件数据作为响应体   打包到响应报文中
        with open(‘33.jpg‘, ‘rb‘) as file:
            html_data = file.read()  # html_data 是二进制bytes字节类型的数据
        # .encode()先把前面的str类型转成bytes字节类型,然后拼接
        response_data = (‘HTTP/1.1 200 OK\r\nServer:PWS2.0\r\n\r\n‘).encode() + html_data
        client_socket.send(response_data)
        # 5.一次请求/响应 就关闭连接  --> 短连接
        client_socket.close()
if __name__ == ‘__main__‘:
    main()
"""
PWS5.0目的:使用协程实现多任务,提高体验
1.>接收请求报文
2.>解析请求报文-得到用户需求
3.>根据用户的需求找到对应的资源
4.>资源打包到HTTP响应报文
最开始肯定是最简单的,一步一步的加多,慢慢地才会出来
PWS2.0:Python Web Server 2.0
主从
master slave
主:接受用户数据
从:干活
leader:
follower:
"""
import socket
import re
import gevent
from gevent import monkey
monkey.patch_all()  # 自动切换  time.sleep recv accept 这些类型的函数在执行的时候会出现大量的耗时等待,所以让这部分闲置时间加以利用.
class HTTPServer:
    """web服务"""
    def __init__(self):
        """初始化操作"""
        # 1. 创建tcp服务器的socket  设置选项 绑定 监听
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind((‘‘, 8999))  # 这里绑定的是服务器的固定端口,目的是让客户端能连接到了我的机器上面之后,可以找到我的这个程序
        server_socket.listen(128)
        # 将socket对象保存在 当前对象的属性中
        self.server_socket = server_socket
    def start(self):
        """启动服务"""
        while True:
            client_socket, client_addr = self.server_socket.accept()
            print(‘接受到%s的连接请求‘ % str(client_addr))
            # 为每个用户创建一个协程,并且启动 运行
            gevent.spawn(self.client_handler, client_socket)
    def client_handler(self,client_socket):
        """处理每个客户端的请求"""
        # 3.接收用户请求报文
        request_data = client_socket.recv(4096)
        # 解码 bytes  --> str
        request_data_str = request_data.decode()
        print(request_data)
        # ps:当用户的请求路径为/时候,表示其请求的是首页homepage
        # 解析用户请求 获取到用户的资源请求路径
        # 正则匹配 只要是有/ 提取请求路径
        # GET /index.html
        result = re.search(r‘^\w+ (/\S*)‘, request_data_str)
        # 判断是否提取成功  成功就取出这个值,不成功结束程序
        if not result:  # 路径为空
            print(‘请求报文格式错误‘)
            client_socket.close()
            return  # 结束 这种情况
        # 尽量扁平结构 不要使用else缩进去,那样的是嵌套结构,这是小技巧
        # 获取请求路径  资源路径
"""
PWS5.0目的:使用协程实现多任务,提高体验
1.>接收请求报文
2.>解析请求报文-得到用户需求
3.>根据用户的需求找到对应的资源
4.>资源打包到HTTP响应报文
最开始肯定是最简单的,一步一步的加多,慢慢地才会出来
PWS2.0:Python Web Server 2.0
主从
master slave
主:接受用户数据
从:干活
leader:
follower:
"""
import socket
import re
import gevent
from gevent import monkey
monkey.patch_all()  # 自动切换  time.sleep recv accept 这些类型的函数在执行的时候会出现大量的耗时等待,所以让这部分闲置时间加以利用.
def client_handler(client_socket):
    """处理每个客户端的请求"""
    # 3.接收用户请求报文
    request_data = client_socket.recv(4096)
    # 解码 bytes  --> str
    request_data_str = request_data.decode()
    print(request_data)
    # ps:当用户的请求路径为/时候,表示其请求的是首页homepage
    # 解析用户请求 获取到用户的资源请求路径
    # 正则匹配 只要是有/ 提取请求路径
    # GET /index.html
    result = re.search(r‘^\w+ (/\S*)‘, request_data_str)
    # 判断是否提取成功  成功就取出这个值,不成功结束程序
    if not result:  # 路径为空
        print(‘请求报文格式错误‘)
        client_socket.close()
        return  # 结束 这种情况
    # 尽量扁平结构 不要使用else缩进去,那样的是嵌套结构,这是小技巧
    # 获取请求路径  资源路径
import socket
import re
import gevent
from gevent import monkey
import sys
monkey.patch_all()  # 自动切换  time.sleep recv accept 这些类型的函数在执行的时候会出现大量的耗时等待,所以让这部分闲置时间加以利用.
class HTTPServer:
    """web服务"""
    def __init__(self, port):
        """初始化操作"""
        # 1. 创建tcp服务器的socket  设置选项 绑定 监听
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind((‘‘, port))  # 这里绑定的是服务器的固定端口,目的是让客户端能连接到了我的机器上面之后,可以找到我的这个程序
        server_socket.listen(128)
        # 将socket对象保存在 当前对象的属性中
        self.server_socket = server_socket
    def start(self):
        """启动服务"""
        while True:
            client_socket, client_addr = self.server_socket.accept()
            print(‘接受到%s的连接请求‘ % str(client_addr))
            # 为每个用户创建一个协程,并且启动 运行
            gevent.spawn(self.client_handler, client_socket)
    def client_handler(self, client_socket):
        """处理每个客户端的请求"""
        # 3.接收用户请求报文
        request_data = client_socket.recv(4096)
        # 解码 bytes  --> str
        request_data_str = request_data.decode()
        print(request_data)
        # ps:当用户的请求路径为/时候,表示其请求的是首页 homepage
        # 解析用户请求 获取到用户的资源请求路径
        # 正则匹配 只要是有/ 提取请求路径
        # GET /index.html
        result = re.search(r‘^\w+(/\S*)‘, request_data_str)
        # 判断是否提取成功  成功就取出这个值,不成功结束程序
        if not result:  # 路径为空
            print(‘请求报文格式错误‘)
            client_socket.close()
            return  # 结束 这种情况
        # 尽量扁平结构 不要使用else缩进去,那样的是嵌套结构,这是小技巧
        # 获取请求路径  资源路径