四、HTTP协议

四、HTTP协议

HTTP浏览器默认以GBK解码数据

'''
HTTP协议:HyperText Transfer Protocol 超本文传输协议

协议的作用就是用来传输超文本 HTML(HyperTextMarkupLanguage)

HTML:超文本标记语言

HTTP:用来传输超文本的一个协议

HTTP协议都是基于TCP的连接,可以使用socket模块来进行交互通信

超文本传输协议 用来规定服务端和浏览器之间的数据交互的格式...

该协议你可以不遵循 但是你写的服务端就不能被浏览器正常访问 你就自己跟自己玩
你就自己写客户端 用户想要使用 就下载你专门的app即可
'''

一、四大特性

'''
1.基于请求响应

2.基于TCP/IP作用于应用层之上的协议

3.无状态
	不保存用户的信息
    eg:一个人来了一千次 你都记不住 每次都当他如初见
    由于HTTP协议是无状态的 所以后续出现了一些专门用来记录用户状态的技术
    	cookie、session、token...

4.无/短链接
  	请求来一次我响应一次 之后我们两个就没有任何链接和关系了
    
    长链接:双方建立连接之后默认不断开 websocket(后面讲项目的时候会讲)

'''

二、HTTP请求/响应数据格式

浏览器基于HTTP与服务器交互,HTTP协议用来规定服务端和浏览器之间的数据交互的格式,其中有:

  • HTTP请求头request headers:一般是浏览器用于向服务器请求数据
  • HTTP响应头response headers:一般是服务器接收到浏览器请求后,返回给浏览器的响应

为了方便使用和学习,HTTP在定义时,响应头与请求头的格式基本一致

1、HTTP响应头

1.1 在浏览器中查看HTTP响应头

在服务器返回给浏览器内容时,需要设置HTTP响应头

  • 第一步:按F12
  • 第二步:选择network
  • 第三步:点击对应的name
  • 第四步:点击headers
  • 第五步:点击Request Headers
  • 第六步:点击Request Headers 右侧的 view parsed 调出网页的HTTP请求头,按照类似该格式书写入send语句

QQ截图202103160010491.2 HTTP响应头的标准格式

响应首行(标识HTTP协议版本,响应状态码)

响应头(一大堆k,v键值对)
\r\n	>>> 此处一定会有一个换行

响应体(返回给浏览器展示给用户看的数据)

1.3 响应头的代码实例

import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8000))
server.listen(5)
client_socket,client_addr = server.accept()

在以上语句后添加上此代码:
#设置完一个响应头,就需要换行一次
client_socket.send(('HTTP/1.1 200 OK\r\n'.encode('utf8')))
'''
....大量相应头

'''
#所有的响应头设置完成后,再换行一次
client_socket.send(('\r\n'.encode('utf8')))

#在上述所有响应头设置完成后,才可以向客户端发送内容
client_socket.send(('helloworld'.encode('utf8')))

使用浏览器访问后,运行结果如下:

QQ截图20210316003859

2、HTTP请求头

2.1 TCP服务器查看HTTP请求头

上述介绍响应头如何书写时,我们服务器也接收到了浏览器的HTTP请求头,在此解释:

GET / HTTP/1.1
'''
GET / HTTP/1.1

GET:请求方式,有GET/POST/PUT/DELETE...
	常用的请求方式有:GET/PUT/POST
		1.get请求
  		朝服务端要数据
    		eg:输入网址获取对应的内容
            
  		2.post请求
  		朝服务端提交数据
    		eg:用户登陆 输入用户名和密码之后 提交到服务端后端做身份校验
/:请求的路径,以及请求参数,例如:
	/index.html?name=jack&age=18
		/index.html	表明请求的路径
		?name=jack&age=18 表名参数
HTTP/1.1:代表HTTP版本号为1.1
'''
Host: 127.0.0.1:8000
'''
Host:表示请求的服务器的IP地址和端口号
'''
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Microsoft Edge";v="90"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36 Edg/90.0.818.39
'''
User-Agent:简称UA,起初设计的目的,是为了能从请求头里辨识浏览器的类型(谷歌、火狐、...)
但是现今失去了此功能,UA也失去了太大价值
'''
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

2.2 请求头标准格式

请求首行(标识HTTP协议版本,当前请求方式)

请求头(一大堆k,v键值对)
\r\n	>>> 此处一定会有一个换行

请求体(并不是所有的请求方式都有,get没有,post有,存放的是post请求提交的敏感数据)

三、请求方式

# 请求方式
	1.get请求
  	朝服务端要数据
    	eg:输入网址获取对应的内容
            
  	2.post请求
  	朝服务端提交数据
    	eg:用户登陆 输入用户名和密码之后 提交到服务端后端做身份校验

四、响应状态码

# 响应状态码
	用一串简单的数字来表示一些复杂的状态或者描述性信息  
404:请求资源不存在
        
1XX:服务端已经成功接收到了你的数据正在处理,你可以继续提交额外的数据
 
2XX:服务端成功响应了你想要的数据(200 OK请求成功)
  
3XX:重定向(当你在访问一个需要登陆之后才能看的页面 你会发现会自动跳转到登陆页面)
  
4XX:请求错误
    404:请求资源不存在
    403:当前请求不合法或者不符合访问资源的条件
  
5XX:服务器内部错误(500)

五、URL

url:统一资源定位符(大白话 网址)

"""
什么是URL?
URL是统一资源定位器(Uniform Resource Locator)的缩写,也被称为网页地址,是因特网上标准的资源的地址。
URL举例
http://www.sohu.com/stu/intro.html
http://222.172.123.33/stu/intro.html

URL地址由4部分组成
第1部分:为协议:http://、ftp://等 
第2部分:为站点地址:可以是域名或IP地址
第3部分:为页面在站点中的目录:stu
第4部分:为页面名称,例如 index.html
各部分之间用“/”符号隔开。

绝对URL - 指向另一个站点
	例如:href="http://www.jd.com"
相对URL - 指当前站点中确切的路径
	例如:href="index.htm"
锚URL - 指向页面中的锚
	例如:href="#top"

六、其他小知识

1、设置浏览器以UTF8编码读取数据

在HTTP响应头中加上:'content-type:text/html;charset:utf8\n'
charset可以指定浏览器的解码方式为UTF8

2、如果页面未找到,设置404界面

将HTTP响应头中'HTTP/1.1 200 OK\r\n'修改为:'HTTP/1.1 404 Page Not Found'

QQ截图20210316200657

3、面对对象的封装HTTP

import socket
class MyServer(object):
    def __init__(self,ip,port):
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.socket.bind((ip,port))
        self.socket.listen(128)
    def run_forever(self):
        client_socket,client_addr = self.socket.accept()
        client_socket.send(('HTTP/1.1 200 OK\r\n'.encode('gbk')))
        data  = client_socket.recv(1024).decode('utf8')
        while True:
            if data:
                a = data.splitlines()[0]
                b = a.split(' ')[1]
                if b == '/login':
                    response_body = '欢迎来到登录页面'
                elif b == '/register':
                    response_body = '欢迎来到注册页面'
                elif b == '/home':
                    response_body = '欢迎来到你家!'
                elif b == '/':
                    response_body = 'SB!'
            else:
                response_body = '无效!'
            client_socket.send((response_body.encode('gbk')))

server = MyServer('0.0.0.0',9090)
server.run_forever()
posted @ 2021-06-04 17:08  zzwYYYYYY  阅读(89)  评论(0)    收藏  举报