HTTP协议
http协议
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)
HTTP协议工作于客户端-服务端架构为上,浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
WEB服务器根据接收到请求后,向客户端发送响应信息
http协议特性
(1)基于tcp/ip
(2)基于请求 - 响应模式
(3)无状态保存
(4)无连接
http请求协议与响应协议
请求协议
请求格式
请求方式:get与post请求
(1)get提交的数据会放在url之后,以?分割url和传输数据,参数之间以&相连
(2)get提交的数据大小有限制(浏览器对url长度有要求)
(3)get与post请求在服务端获取请求数据方式不同
响应协议
响应格式
响应状态码
状态码的职 是当客户端向服务器端发送请求时, 返回的请求 结果。借助状态码,用户可以知道服务器端是正常 理了请求,还是出 现了 。状态码如200 OK,以3位数字和原因 成。数字中的 一位指定了响应 别,后两位无分 。响应 别有以5种。
示例
(1)socket服务端,并启动运行
import socket sk = socket.socket() sk.bind(("127.0.0.1",8800)) sk.listen(5) while True: print("server waiting...") conn,addr = sk.accept() data = conn.recv(1024) print(data) conn.send(b"HTTP/1.1 200 OK\r\n\r\nHello World!") """ 发送响应时需要遵守http协议的响应格式,否则在浏览器会报错 """ conn.close()
(2)在浏览器输入IP:端口,效果如下
同时在服务器端可以查看接受的数据
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: none\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=MTB0jmt6lcLUJoJJp6yMZ1bSDg6Nj4Nti0uds6mx4uYfbmSZr5s7QXfrtIkv0KvG\r\n\r\n' server waiting... b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nSec-Fetch-Mode: no-cors\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nSec-Fetch-Site: same-origin\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=MTB0jmt6lcLUJoJJp6yMZ1bSDg6Nj4Nti0uds6mx4uYfbmSZr5s7QXfrtIkv0KvG\r\n\r\n' server waiting...
可以看到有个favicon.ico这个时图标请求,可以在服务端修改
--创建一个html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <link rel="icon" href="https://www.jd.com/favicon.ico"> </head> <body> <h1>Hello World </h1> </body> </html>
--修改服务端代码
import socket sk = socket.socket() sk.bind(("127.0.0.1",8800)) sk.listen(5) while True: print("server waiting...") conn,addr = sk.accept() data = conn.recv(1024) print(data) with open("index.html","rb") as f: html = f.read() conn.send(b"HTTP/1.1 200 OK\r\n\r\n%s"%html) """ 发送响应时需要遵守http协议的响应格式,否则在浏览器会报错 """ conn.close()
重新运行服务端,输入ip,效果如下
查看服务端接受数据
server waiting... b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: none\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=MTB0jmt6lcLUJoJJp6yMZ1bSDg6Nj4Nti0uds6mx4uYfbmSZr5s7QXfrtIkv0KvG\r\n\r\n' server waiting... b'' server waiting...
与form表单结合使用
(1)创建一个form表单文件 input标签中需要添加name在服务端才能接受到数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://127.0.0.1:8800" method="get"> <p>username:<input type="text" name="user"></p> <p>password:<input type="password" name="pwd"></p> <p>sex: <input type="radio" name="M">M <input type="radio" name="F">F </p> <p><input type="submit"></p> </form> </body> </html>
(2)浏览器运行,填入数据点击提交
--在浏览器的url可以看到对应数据
--在服务端接受数据如下
b'GET /?user=abc&pwd=123&M=on HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: cross-site\r\nReferer: http://localhost:63342/python/test/form_table.html?_ijt=eekrrf89lamd86eqkq34k3e9tr\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=MTB0jmt6lcLUJoJJp6yMZ1bSDg6Nj4Nti0uds6mx4uYfbmSZr5s7QXfrtIkv0KvG\r\n\r\n'
(3)将form表单中请求改为post请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://127.0.0.1:8800" method="post"> <p>username:<input type="text" name="user"></p> <p>password:<input type="password" name="pwd"></p> <p>sex: <input type="radio" name="M">M <input type="radio" name="F">F </p> <p><input type="submit"></p> </form> </body> </html>
--浏览器打开提交
返回页面如下:
服务端请求如下:
b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nContent-Length: 21\r\nCache-Control: max-age=0\r\nOrigin: http://localhost:63342\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: cross-site\r\nReferer: http://localhost:63342/python/test/form_table.html?_ijt=t9i6n11m09bgn87rjt9qn0mnj2\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=MTB0jmt6lcLUJoJJp6yMZ1bSDg6Nj4Nti0uds6mx4uYfbmSZr5s7QXfrtIkv0KvG\r\n\r\nuser=abc&pwd=123&F=on'
在服务端最后可以得到输入的数据:user=abc&pwd=123&F=on'