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数据到前端 

posted @ 2024-05-03 21:46  leagueandlegends  阅读(35)  评论(0)    收藏  举报