web應用和http協議

1、web應用

  Web應用程序是一種能夠經過Web訪問的應用程序;html

  程序的最大好處是用戶很容易訪問應用程序,用戶只須要有瀏覽器便可,不須要再安裝其餘軟件。java

  應用程序有兩種模式C/S、B/Spython

  一、C/S是客戶端/服務器端程序,也就是說這類程序通常獨立運行。web

  二、B/S就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助谷歌,火狐等瀏覽器來運行。編程

  WEB應用程序通常是B/S模式。Web應用程序首先是「應用程序」,和用標準的程序語言,如java,python等編寫出來的程序沒有什麼本質上的不一樣。在網絡編程的意義下,瀏覽器是一個socket客戶端,服務器是一個socket服務端。瀏覽器

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'


import socket

sock = socket.socket()
sock.bind(("127.0.0.1", 8800))  # 服務器地址和端口
sock.listen(5)

while True:
    print("server waiting.......")
    # conn:客戶端套接字對象,addr:
    conn, addr = sock.accept()  # 等待用戶鏈接
    data = conn.recv(1024)
    print(data)

    # 響應首行(HTTP/1.1 200 OK)、響應體
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n<h1>hello luffycity!</h1>")  # 通常都是須要兩個空格分隔\r\n\r\n

    conn.close()

    """
    server waiting.......
    b'GET / HTTP/1.1\r\n
    Host: 127.0.0.1:8800\r\n
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:59.0) Gecko/20100101 Firefox/59.0\r\n
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n
    Accept-Encoding: gzip, deflate\r\n
    Connection: keep-alive\r\nUpgrade-Insecure-Requests: 1
    \r\n\r\n'
    
    請求首行裏有多個請求頭,每一個請求頭用\r\n進行區分。  直到出現\r\n\r\n時,後面的爲請求體。

    get請求沒有請求體,請求體是給post請求用的。
    """

2、web框架

  Web框架(Web framework)是一種開發框架,用來支持動態網站、網絡應用和網絡服務的開發。這大多數的web框架提供了一套開發和部署網站的方式,也爲web行爲提供了一套通用的方法。web框架已經實現了不少功能,開發人員使用框架提供的方法而且完成本身的業務邏輯,就能快速開發web應用了。瀏覽器和服務器的是基於HTTP協議進行通訊的。也能夠說web框架就是在如下十幾行代碼基礎張擴展出來的,有不少簡單方便使用的方法,大大提升了開發的效率。緩存

import socket

def handle_request(client):

    request_data = client.recv(1024)
    print("request_data: ",request_data)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    client.send("<h1 style='color:red'>Hello, 路飛學城! </h1>".encode("utf8"))

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8800))
    sock.listen(5)

    while True:
        print("the server is waiting for client-connection....")
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':

    main()

3、http協議

一、HTTP協議簡介

  HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於萬維網(WWW:World Wide Web )服務器與本地瀏覽器之間傳輸超文本的傳送協議。安全

HTTP是一個屬於應用層的面向對象的協議,因爲其簡捷、快速的方式,適用於分佈式超媒體信息系統。它於1990年提出,通過幾年的使用與發展,獲得不斷地完善和擴展。HTTP協議工做於客戶端-服務端架構爲上。瀏覽器做爲HTTP客戶端經過URL向HTTP服務端即WEB服務器發送全部請求。Web服務器根據接收到的請求後,向客戶端發送響應信息。服務器

  

二、HTTP協議特色

  • 基於TCP/IP網絡

  計算機與網絡設備要相互通訊,雙方就必須基於相同的方法。好比,如何探測到通訊目標、由哪一邊先發起通訊、使用哪一種語言進行通 信、怎樣結束通訊等規則都須要事先肯定。不一樣的硬件、操做系統之間 的通訊,全部的這一切都須要一種規則。而咱們就把這種規則稱爲協議(protocol)。協議中存在各式各樣的內容。從電纜的規格到IP地址的選定方法、 尋找異地用戶的方法、雙方創建通訊的順序,以及Web頁面顯示須要 處理的步驟,等等。像這樣把與互聯網相關聯的協議集合起來總稱爲TCP/IP。

  http協議是基於TCP/IP協議之上的應用層協議。

  • 基於請求——響應模式

  HTTP協議規定,請求從客戶端發出,最後服務器端響應該請求並 返回。換句話說,確定是先從客戶端開始創建通訊的,服務器端在沒有 接收到請求以前不會發送響應。

  

  • 無狀態保存

  HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議自身不對請求和響應之間的通訊狀態進行保存。也就是說在HTTP這個級別,協議對於發送過的請求或響應都不作持久化處理 

  

  使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產生。協議自己並不保留以前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特地把HTTP協議設計成 如此簡單的。但是,隨着Web的不斷髮展,因無狀態而致使業務處理變得棘手的狀況增多了。好比,用戶登陸到一家購物網站,即便他跳轉到該站的 其餘頁面後,也須要能繼續保持登陸狀態。針對這個實例,網站爲了能 夠掌握是誰送出的請求,須要保存用戶的狀態。HTTP/1.1雖然是無狀態協議,但爲了實現指望的保持狀態功能, 因而引入了Cookie技術有了Cookie再用HTTP協議通訊,就能夠管理狀態了

  • 無鏈接

  無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。

4、請求協議和響應協議

  http協議包含由瀏覽器發送數據到服務器須要遵循的請求協議服務器發送數據到瀏覽器須要遵循的請求協議。用於HTTP協議交互的信被爲HTTP報文。請求端(客戶端)的HTTP報文作請求報文,響應端(服務器端)的作響應報文。HTTP報文自己是由多行數據構成的字文本。

  

一、請求協議

  (1)請求格式

  

  (2)get請求與post請求區別

  • GET提交的數據會放在URL以後,以?分割URL和傳輸數據,參數之間以&相連,如EditBook?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的請求體中.
  • GET提交的數據大小有限制(由於瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
  • GET與POST請求在服務端獲取請求數據方式不一樣
  • GET方式提交數據,會帶來安全問題,好比一個登陸頁面,經過GET方式提交數據時,用戶名和密碼將出如今URL上,若是頁面能夠被緩存或者其餘人能夠訪問這臺機器,就能夠從歷史記錄得到該用戶的帳號和密碼.

  代碼示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello luffycity!</h1>
    <img src='https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=16535fed6163f6241c5d3e05bf7f8cc5/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg'>
    <a href="http://www.luffycity.com">click</a>
</body>
</html>
index.html
# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'

import socket

sock = socket.socket()
sock.bind(("127.0.0.1",8800))   # 服務器地址和端口
sock.listen(5)


while True:
    print("server waiting.......")
    # conn:客戶端套接字對象,addr:
    conn,addr = sock.accept()  # 等待用戶鏈接
    data = conn.recv(1024)
    print("data", data)

    # 讀取html文件
    with open("index.html", "r") as f:
        data = f.read()

    # 響應首行(HTTP/1.1 200 OK)、響應體
    # conn.send(b"HTTP/1.1 200 OK\r\n\r\n<h1>hello luffycity!</h1>")   # 通常都是須要兩個空格分隔\r\n\r\n

    # 響應首行和html文件讀取出來的響應體,統一編碼爲二進制格式發送給瀏覽器
    conn.send(("HTTP/1.1 200 OK\r\n\r\n%s" % data).encode('utf-8'))

    conn.close()
    """
    請求首行裏有多個請求頭,每一個請求頭用\r\n進行區分。  直到出現\r\n\r\n時,後面的爲請求體。
    
    get請求沒有請求體,請求體是給post請求用的。
    
    GET提交的數據會放在URL以後,以?分割URL和傳輸數據:http://127.0.0.1:8800/yuan?name=yuan&age=22
    b'GET /yuan?name=yuan&age=22 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 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,und;q=0.8\r\n\r\n'
    
    請求體(a=1&b=2)  # 注意只有post請求才有請求體
    
    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 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,und;q=0.8\r\n\r\n'
    
    url:
    協議://IP:端口(80)/路徑?a=1&b=2
    """ 

二、響應協議 

  (1)響應格式

  響應協議是服務器給瀏覽器發的字符串,響應報文的組成:
  響應首行:HTTP/1.1 200 OK 分別是:協議版本、狀態碼、狀態碼的緣由短語
  響應頭:服務器解釋給瀏覽器的行爲
  響應體:瀏覽器拿到後要渲染的內容,前面也須要\r\n\r\n換行,與響應頭區分

 

  

  (2)響應狀態碼

  狀態碼的值是當客戶端向服務器端發送請求時, 返回的請求結果。藉助狀態碼,用戶能夠知道服務器端是正常處理了請求,仍是出現了問題。

  狀態碼如200 OK,以3位數字組成。數字中的一位指定了響應級別,響應級別有如下5種。

  

  代碼示例:

<!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">
        用戶名 <input type="text" name="user">
        密碼 <input type="password" name="pwd">
        <input type="submit">
    </form>
</body>
</html>
login.html
# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'

import socket

sock = socket.socket()
sock.bind(("127.0.0.1",8801))   # 服務器地址和端口
sock.listen(5)


while True:
    print("server waiting.......")
    # conn:客戶端套接字對象,addr:
    conn,addr = sock.accept()  # 等待用戶鏈接
    data = conn.recv(1024)
    print("data", data)

    # 讀取html文件
    # with open("index.html", "r") as f:
    with open("login.html", "rb") as f:
        data = f.read()

    # 請求首行(HTTP/1.1 200 OK)、請求體
    # conn.send(b"HTTP/1.1 200 OK\r\n\r\n<h1>hello luffycity!</h1>")   # 通常都是須要兩個空格分隔\r\n\r\n

    # 響應首行和html文件讀取出來的相應體,統一編碼爲二進制格式發送給瀏覽器
    conn.send(b"HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n%s" % data)

    conn.close()
    """
    user=xiugeng&pwd=123   # 只有post請求才有請求體數據
    
    b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nContent-Length: 20\r\nCache-Control: max-age=0\r\nOrigin: http://127.0.0.1:8800\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,und;q=0.8\r\n\r\nuser=xiugeng&pwd=123'
    """

  總結使用get或post的狀況:

  一、通常查詢的時候用get請求
  二、通常修改更新的時候用post請求

4、wsgiref模塊

  最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。

  若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。

  正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。這個接口就是WSGI:Web Server Gateway Interface。而wsgiref模塊就是python基於wsgi協議開發的服務模塊。

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'

from wsgiref.simple_server import make_server

def application(environ, start_response):
    # 按着http協議解析數據(字典):environ
    # 按着http協議進行組裝數據(函數):start_response
    print(environ)   #'PATH_INFO': '/index'
    print(type(environ))  # <class 'dict'>
    # 當前的請求路徑
    path = environ.get("PATH_INFO")
    start_response('200 OK', [])

    if path == "/login":
        with open("login.html", "r") as f:
            data = f.read()
    elif path == "/index":
        with open("index.html", "r") as f:
            data = f.read()
    return [data.encode("utf8")]

    # return [b"<h1>hello web<h1>"]   # wsgi要求return的時候要加上列表

# 封裝socket
"""
sock = socket.socket()
sock.bind(("127.0.0.1",8090))   # 服務器地址和端口
sock.listen(5)
"""
httped = make_server('', 8090, application)

# 等待用戶連接
"""
conn,addr = sock.accept() 
"""
httped.serve_forever()   # 收到連接調用application函數

  本質上講,這個文件就能夠稱爲一個web框架。  

5、DIY一個WEB框架

相關文章
相關標籤/搜索