HTTP协议
一、HTTP协议定义
HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写。它的发展是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC。http是应用层协议。
HTTP协议永远都是客户端发起请求,服务器回送相应,这样就限制了使用HTTP协议,无法实现客户端没有发起请求的时候,服务器将消息推送给客户端。HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求没有对应关系。http协议是单向的。
HTTP协议是一个纯文本协议,这意味着我们直接传递纯文本就可以了。换句话说,一个web服务器其实就是根据约定好的方法生成对应的HTTP消息内容,然后传递给对方。
二、HTTP的协议特点
简单快速:只需要传递方法和路径
灵活:http可以传递任意类型的数据对象。通过content-type指定
无连接:无连接意味着每次连接处理一个请求,服务器返回之后断开连接,节省传输时间和服务器压力。
无状态:无状态是指协议对于事物处理没有记忆能力,需要通过cookie和session来加以区别。
支持B/S模式和C/S模式。

三、HTTP报文

四、HTTP请求

GET请求例子,使用Fiddler抓取的request:
https://www.baidu.com/s?wd=url
客户端请求:
GET /s?wd=url HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.48 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,id;q=0.7
Cookie: BAIDUID=FB1F9E174367B4FEA9808A2758FC9120:FG=1; BIDUPSID=FB1F9E174367B4FEA9808A2758FC9120; PSTM=1536716563; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; MSA_WH=360_640; lsv=globalTjs_7a56b8a-wwwTcss_978f62a-wwwBcss_480c272-framejs_1983a82-globalBjs_3aafc04-sugjs_86ad242-wwwjs_4e66662; H_WISE_SIDS=126087_125822_125794_125807_124692_124475_125650_124610_125897_120160_118880_118860_118839_118818_118786_107320_125544_125007_117327_124978_117432_125776_125926_125652_124939_125172_125709_126092_125852_126055_124035_125058_110085_123290_125645_125874_125451; plus_cv=1::m:d03af37f; BDRCVFR[t8qxwL5sMGc]=mk3SLVN4HKm; delPer=0; BD_CK_SAM=1; PSINO=2; BDRCVFR[M7pOaqtZgJR]=I67x6TjHwwYf0; H_PS_PSSID=26523_1434_26964_21080_18560_22159; H_PS_645EC=041dGI532V5Qr06mZYBIPdPhh7h0POnOmQuxoRfNHNnDCnisahtbf78BAHc; BDSVRTM=0; pgv_pvi=9362056192; pgv_si=s7875444736
第一部分:请求行,即第一行,用来说明请求类型,要访问的资源以及所使用的HTTP版本。
GET说明请求类型为GET,[/s?wd=url]为要访问的资源,该行的最后一部分说明使用的是HTTP 1.1版本。
第二部分:请求头部,从第二行起,用来说明服务器要使用的附加信息。
HOST将指出请求的目的地,User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础。该信息由你的浏览器来定义,并且在每个请求中自动发送等等。
第三部分:空行,请求头部后面的空行是必须的。即使第四部分的请求数据为空,也必须有空行。
第四部分:请求数据也叫主体,可以添加任意的其他数据。这个例子的请求数据为空。
POST请求例子,使用Fiddler抓取的request:
https://zhidao.baidu.com/business/submit/onbusinessbrowse
客户端请求:
POST /business/submit/onbusinessbrowse HTTP/1.1
Host: zhidao.baidu.com
Connection: keep-alive
Content-Length: 146
Pragma: no-cache
Cache-Control: no-cache
Origin: https://zhidao.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.48 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
X-ik-token: fb5f224884c6656a54ebc8a349efda5a
X-ik-ssl: 1
Referer: https://zhidao.baidu.com/question/12717124.html?hideOtherAnswer=true
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,id;q=0.7
Cookie: BAIDUID=FB1F9E174367B4FEA9808A2758FC9120:FG=1; BIDUPSID=FB1F9E174367B4FEA9808A2758FC9120; PSTM=1536716563; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_WISE_SIDS=126087_125822_125794_125807_124692_124475_125650_124610_125897_120160_118880_118860_118839_118818_118786_107320_125544_125007_117327_124978_117432_125776_125926_125652_124939_125172_125709_126092_125852_126055_124035_125058_110085_123290_125645_125874_125451; BDRCVFR[t8qxwL5sMGc]=mk3SLVN4HKm; PSINO=2; BDRCVFR[M7pOaqtZgJR]=I67x6TjHwwYf0; pgv_pvi=9362056192; pgv_si=s7875444736; H_PS_PSSID=26523_1434_21080_18560_22159; ZD_ENTRY=baidu; Hm_lvt_6859ce5aaf00fb00387e6434e4fcc925=1537170710,1537928534,1537932933,1538040431; BDUSS=plbXhMdzQ2eFRnODVjWGtZcEhSeGttVTNodEVXekh3dFRuY3BhbGRtUDBMOVJiQVFBQUFBJCQAAAAAAAAAAAEAAACpgSAjbmV3bW9ybmluZzIwMTEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSirFv0oqxbek; Hm_lpvt_6859ce5aaf00fb00387e6434e4fcc925=1538040575
第一部分:请求行,第一行讲明了是post请求,以及http1.1版本。
第二部分:请求头部,第二行至第十七行。
第三部分:空行,第十八行的空行。
第四部分:请求数据,空。
HTTP GET POST请求
http_server.py# socket服务端
import socket
import threading
import json
server = socket.socket()
# 绑定到0.0.0.0 8000端口
server.bind(('0.0.0.0', 8000))
server.listen()
# 获取客户端连接并启动线程去处理
def handle_sock(sock, addr):
while True:
tmp_data = sock.recv(1024)
tmp_data = tmp_data.decode("utf8")
print(tmp_data)
request_line = tmp_data.splitlines()[0]
print(request_line)
if request_line:
method = request_line.split()[0]
path = request_line.split()[1]
if method == "GET":
response_template = '''HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<form action="/" method="POST">
<input type="text" value="name" />
<input type="password" value="password">
<input type="submit" value="登录">
</form>
</body>
</html>
'''
sock.send(response_template.encode("utf8"))
# sock.close()
break
elif method == "POST":
response_template = '''HTTP/1.1 200 OK\r\nContent-Type: application/json
{}
'''
data = [
{
"name": "django打造在线教育",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/78.html"
},
{
"name": "python高级编程",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/200.html"
},
{
"name": "scrapy分布式爬虫",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/92.html"
},
{
"name": "diango rest framework打造生鲜电商",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/131.html"
},
{
"name": "tornado从入门到精通",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/290.html"
},
]
sock.send((response_template.format(json.dumps(data)).encode("utf8")))
# sock.close()
break
while True:
# 阻塞等待连接
socket, add = server.accept()
# 启动一个线程去处理新的用户连接
client_thread = threading.Thread(target=handle_sock, args=(socket, add))
client_thread.start()

运行结果:访问127.0.0.1:8000

点击登录按钮

五、HTTP协议Python实例
Python向网页上返回一行HTML文本
http_server.py

#socket服务端
import socket
import threading
server_socket = socket.socket()
#绑定到0.0.0.0 8000端口
server_socket.bind(('0.0.0.0',8000))
server_socket.listen()
#获取客户端连接并启动线程去处理
def handle_client(server_socket,addr):
while True:
tmp_data = socket.recv(1024)
print(tmp_data.decode("utf-8"))
response_template = '''HTTP/1.1 200 OK
<html>
<head>
<title>Build A Web Server</title>
</head>
<body>
Hello,world,this is a very simple HTML document.
</body>
</html>
'''
socket.send(response_template.encode("utf-8"))
while True:
# 阻塞等待连接
socket, add = server_socket.accept()
#启动一个线程去处理新的用户连接
client_thread=threading.Thread(target=handle_client,args=(socket,add))
client_thread.start()
运行后访问http://127.0.0.1:8000/

如果删除“HTTP/1.1 200 OK",则不是一个标准的HTTP请求。只有按照HTTP协议的要求组成字符串才可以自己手动写HTTP协议。
HTTP模拟访问百度,可以获取百度HTTP请求
socket_http.py
import socket
http_client = socket.socket()
http_client.connect(('www.baidu.com', 80))
http_client.send("GET / HTTP/1.1\r\nConnection:close\r\n\r\n".encode("utf-8"))
data = b""
while True:
tmp=http_client.recv(1024)
if tmp:
data+=tmp
else:
break
print(data.decode("utf-8"))
运行结果如下:

Python向网页上发送Json数据
# socket服务端
import socket
import json
import threading
server_socket = socket.socket()
# 绑定到0.0.0.0 8000端口
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen()
# 获取客户端连接并启动线程去处理
def handle_client(server_socket, addr):
while True:
tmp_data = server_socket.recv(1024)
print(tmp_data.decode("utf-8"))
# 创建一个JSON响应
response_data = json.dumps({'key': 'value'}).encode('utf-8')
# 发送HTTP响应头
response_header = b'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n' % len(
response_data)
server_socket.send(response_header)
# 发送JSON数据
server_socket.send(response_data)
# 关闭客户端连接
server_socket.close()
break
while True:
# 阻塞等待连接
socket, add = server_socket.accept()
# 启动一个线程去处理新的用户连接
client_thread = threading.Thread(target=handle_client, args=(socket, add))
client_thread.start()
运行结果如下:

json_server.py
#socket服务端
import json
import socket
import threading
server_socket = socket.socket()
#绑定到0.0.0.0 8000端口
server_socket.bind(('0.0.0.0',8000))
server_socket.listen()
#获取客户端连接并启动线程去处理
def handle_client(server_socket,addr):
while True:
tmp_data = socket.recv(1024)
print(tmp_data.decode("utf-8"))
response_template = '''HTTP/1.1 200 OK
Content-Type: application/json
{}
'''
data=[
{
"name":"django打造在线教育",
"teacher":"bobby",
"url": "https://coding.imooc.com/class/78.html"
},
{
"name": "python高级编程",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/200.html"
},
{
"name": "scrapy分布式爬虫",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/92.html"
},
{
"name": "diango rest framework打造生鲜电商",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/131.html"
},
{
"name": "tornado从入门到精通",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/290.html"
},
]
socket.send((response_template.format(json.dumps(data)).encode("utf8")))
socket.close()
break
while True:
# 阻塞等待连接
socket, add = server_socket.accept()
#启动一个线程去处理新的用户连接
client_thread=threading.Thread(target=handle_client,args=(socket,add))
client_thread.start()
运行结果如下:

Python html从后台获取json数据值
程序结构:

json_server.py
#socket服务端
import json
import socket
import threading
server_socket = socket.socket()
#绑定到0.0.0.0 8000端口
server_socket.bind(('0.0.0.0',8000))
server_socket.listen()
#获取客户端连接并启动线程去处理
def handle_client(server_socket,addr):
while True:
tmp_data = socket.recv(1024)
print(tmp_data.decode("utf-8"))
response_template = '''HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: http://localhost:63342
{}
'''
data=[
{
"name":"django打造在线教育",
"teacher":"bobby",
"url": "https://coding.imooc.com/class/78.html"
},
{
"name": "python高级编程",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/200.html"
},
{
"name": "scrapy分布式爬虫",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/92.html"
},
{
"name": "diango rest framework打造生鲜电商",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/131.html"
},
{
"name": "tornado从入门到精通",
"teacher": "bobby",
"url": "https://coding.imooc.com/class/290.html"
},
]
socket.send((response_template.format(json.dumps(data)).encode("utf8")))
socket.close()
break
while True:
# 阻塞等待连接
socket, add = server_socket.accept()
#启动一个线程去处理新的用户连接
client_thread=threading.Thread(target=handle_client,args=(socket,add))
client_thread.start()
hello-html.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery-3.5.1.min.js"></script>
<script>
$(document).ready(function (){
$.ajax({
"url":"http://127.0.0.1:8000",
success:function (data) {
for(let value of data){
$("table").append("<tr>\n" +
" <td>"+value.name+"</td>\n" +
" <td>"+value.teacher+"</td>\n" +
" <td><a href=\""+value.url+"\">访问</a></td>\n" +
" </tr>")
}
}
})
})
</script>
</head>
<body>
<div id="info">
<p style="color: blue">讲师信息</p>
<div class="teacher_info">
Python全栈工程师
<p class="age">年龄:29</p>
<p class="name">姓名:bobby</p>
<p class="work_years">工作年限:7年</p>
<p class="position">职位:python开发工程师</p>
</div>
<p style="color:aquamarine">课程信息</p>
<table class="courses">
<th>课程名称</th>
<th>讲师</th>
<th>地址</th>
</table>
</body>
</html>
运行结果如下:

这样可以从服务器返回json数据到前端

浙公网安备 33010602011771号