WEB框架本质和套接字实现web server

http协议:规定了浏览器与服务器之间发送消息的格式。

 

HTTP GET请求的格式:

请求方式 路径 协议版本

请求头部

空一行

请求的数据(get可以不携带)

 

HTTP响应的格式:

协议版本 状态码 状态描述

响应头部(可以没有)

空一行

响应正文

 

Web框架的本质:
A:收发消息相关(django用wsgiref

B:根据不同URL返回不同内容

C:字符串替换

 

Pythonweb框架分类:

自己实现abc:tornado

自己实现bc:django

自己实现b:flask

 

按照另一维度分类:

运维开发:Django

后端:tornado

爬虫:flask

 

Socket套接字版本的web server

想要我们的web server端运行起来就必须要给客户端回复的消息符合http协议规定的格式。

import socket

sk=socket.socket()

sk.bind(('127.0.0.1',8080))

sk.listen()

while True:

    conn,addr=sk.accept()

    data=conn.recv(1024)

    print(data.decode('utf-8'))

    conn.send(b'HTTP/1.1 200 OK/r/n/r/n<h1>hello world</h1>')

    conn.close()
View Code

socket套接字增强版web server

import socket

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,addr=server.accept()
    data=conn.recv(1024)
    data=data.decode('utf-8')#将字节类型转换为字符串
    data1=data.split('\r\n')[0]
    url=data1.split()[1]#从浏览器发过来的消息中分离出访问路径
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n<strong>hello world</strong>')

    if url=='/index/':#根据不同url返回不同内容

        response=b'index page'

    elif url=='/home/':

        response=b'home page'
    else:
        response=b'<h1>404 not found</h1>'
 
    conn.send(response)
    conn.close()
View Code

返回具体的HTML文件

import socket

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

def index(url):
    return b'<h1>welcome to index page</h1>'

def home(url):
    return b'<h1>welcome to home page</h1>'

def login(url):
    with open('login.html','rb') as f:
        return f.read()

url2func=[
    ('/index/',index),
    ('/home/',home),
    ('/login/',login),
]

while True:
    conn,addr=server.accept()
    data=conn.recv(1024)
    data=data.decode('utf-8')
    d=data.split('\r\n')[0]
    url=d.split()[1]
    print(url)

    func=None

    for i in url2func:
        if url==i[0]:
            func=i[1]
            break
    else:
        func=None

    if func:
        msg=func(url)
    else:
        msg=b'<h1>404 not found</h1>'

    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    conn.send(msg)
    conn.close()
View Code

返回动态HTML

import socket
import time

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8888))
server.listen()

def home(url):
    s = "this is {} page!".format(url)
    return bytes(s, encoding="utf8")

def index(url):
    return b'<h1>index page</h1>'

def user(url):
    # 不同的用户得到的页面上显示不同的时间
    c_time = str(time.time())

    with open("user.html", "r") as f:
        data_s = f.read()
        data_s = data_s.replace("@@xx@@", c_time)  # 替换后的字符串数据
        return bytes(data_s, encoding="utf8")

def login(url):
    with open("login.html", "rb") as f:
        return f.read()

# url和将要执行的函数的对应关系
url2func = [
    ("/index/", index),
    ("/home/", home),
    ("/user/", user),
    ("/login/", login),
]

while 1:
    conn, addr = server.accept()
    data = conn.recv(8096)  # 收消息
    # print(data)
    # 从浏览器发送消息中,拿到用户访问的路径
    data_str = str(data, encoding="utf8")
    # print(data_str)
    url = data_str.split("\r\n")[0].split(" ")[1]
    print(url)

    func = None
    for i in url2func:
        if url == i[0]:
            func = i[1]  # 拿到将要执行的函数
            break
    else:
        func = None

    if func:
        msg = func(url)  # 执行对应的函数
    else:
        msg = b'<h1>404</h1>'  # 找不到要执行的函数就返回404

    # 按照HTTP协议的格式要求 回复消息
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 发送状态行
    conn.send(msg)  # 发送响应体
    conn.close()
View Code

WSGIREF版返回动态的HTML文件

import time
from wsgiref.simple_server import make_server

def home(url):
    return bytes('this is {} page'.format(url),encoding='utf-8')

def index(url):
    return bytes('<h1> this is index page',encoding='utf-8')

def test(url):
    ct=str(time.time())
    with open('test.html','r') as f:
        data_s=f.read()
        data_s=data_s.replace('@@xx@@',ct)
        return bytes(data_s,encoding='utf8')

def login(url):
    with open('login.html','rb') as f:
        return f.read()

url2func=[
    ('/home/',home),
    ('/index/',index),
    ('/test/',test),
    ('/login/',login),
]

def run_server(environ,start_response):
    start_response('200 OK',[('Content-Type','text/html;charset=utf8'),])
    url=environ['PATH_INFO']
    func=None
    for i in url2func:
        if i[0]==url:
            func=i[1]
            break
    else:
        func=None
    if func:
        msg=func(url)
    else:
        msg=b'404 NOT FOUND'
    return [msg,]

if __name__=='__main__':
    httpd=make_server('127.0.0.1',8080,run_server)
    print('8080 port')
    httpd.serve_forever()
View Code

jinja2版的返回动态HTML文件

from wsgiref.simple_server import make_server
from jinja2 import Template
import pymysql

def index(url):
    return bytes('this is {} page'.format(url),encoding='utf8')

def home(url):
    return b'<h1>welcome to home page</h1>'

def user(url):
    conn=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='root',
        database='my_system',
        charset='utf8',
    )
    cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute('select * from user')
    ret=cursor.fetchall()
    print(ret)
    with open('user.html','r',encoding='utf8')  as f:
        data=f.read()
        template=Template(data)
        msg=template.render({"user_list": ret})
        return bytes(msg,encoding='utf8')

def login(url):
    with open('login.html','rb') as f:
        return f.read()

url2func=[
    ('/index/',index),
    ('/home/',home),
    ('/user/',user),
    ('/login/',login),
]

def run_server(environ,start_response):
    start_response('200 OK',[('Content-Type','text/html;charset=utf8'),])
    url=environ['PATH_INFO']
    func=None

    for i in url2func:
        if url==i[0]:
            func=i[1]
            break
    else:
        func=None

    if func:
        msg=func(url)
    else:
        msg=b'<h1>404</h1>'
    return [msg,]

if __name__=='__main__':
    httpd=make_server('127.0.0.1',8080,run_server)
    print('8080 port')
    httpd.serve_forever()
View Code

jinja2(html部分)

<table border="1">
    <thead>
    <tr>
        <th>id</th>
        <th>name</th>
        <th>hobby</th>
    </tr>
    </thead>
    <tbody>
    {%for user in user_list%}
    <tr>
        <td>{{user.id}}</td>
        <td>{{user.name}}</td>
        <td>{{user.hobby}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
View Code

下载Django

下载版本:1.11.x

第一种方式(用pip3):Pip3 install Django==1.11.11

第二种方式(Pycharm安装):

Settings=>project:front_end=>project interpreter=>点击+号=>输入django=>选择版本=>勾选Specify version=>点install package

posted @ 2018-06-11 20:38  桥前石头  阅读(389)  评论(0编辑  收藏  举报