day57 手写socket、路由系统、响应一个动态内容、链接数据库、django配置、及应用、DNS服务器

自定义一个简单的web框架

1纯生socket
import socket

def run():
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen(5)

while True:
conn, addr = sk.accept()
data = conn.recv(8096)
# print(data)

conn.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='utf-8'))
conn.send(bytes('hello http', encoding='utf-8'))


if __name__ == '__main__':
run()

2根据输入不同的url,获得不一梓的相应内容
需要找到请求的uri,是/还是index/还是login

import socket

def run():
sk = socket.socket()
sk.bind(('127.0.0.1', 8989))
sk.listen(5)

while True:
conn, addr = sk.accept()
data = conn.recv(8096)
# print('收到的信息1', data)

# 拆分请求信息,拿到uri
# 拿到第一大块
header_list = str(data, encoding='utf-8').split('\r\n\r\n')[0]
# print('收到的信息2', header_list[0])

# 拿到第一大块的第一行
content_list = header_list.split('\r\n')[0] # GET / HTTP/1.1
# print(content_list)

uri = content_list.split(' ')[1] # /
print(uri)

res = None

if uri == '/xxx':
res = bytes('this is xxx', encoding='utf-8')
elif uri == '/ooo':
res = bytes('this is ooo', encoding='utf-8')
elif uri == '/':
res = bytes('ok', encoding='utf-8') # \r\n的斜杠不要写反了
else:
res = bytes('404', encoding='utf-8')
conn.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='utf-8')) # \r\n的斜杠不要写反了
conn.send(res)
conn.close()


if __name__ == '__main__':
run()


3.uri 和函数的对应关系, 一下if很啰嗦
路由系统 响应一个html文件给浏览客户端,【静态网站】fn1
import socket

def fn1():
# return bytes('this is xxx', encoding='utf-8')
fp = open('index_3.html', 'r', encoding='utf-8')
data = fp.read()
return bytes(data, encoding='utf-8') # 响应一个html文件给浏览客户端

def fn2():
return bytes('this is index', encoding='utf-8')

def fn3():
return bytes('this is kkk', encoding='utf-8')

routes = [
('/xxx', fn1),
('/index', fn2),
('/kkk', fn3)
]




def run():
sk = socket.socket()
sk.bind(('127.0.0.1', 8989))
sk.listen(5)

while True:
conn, addr = sk.accept()
data = conn.recv(8096)
# print('收到的信息1', data)

# 拆分请求信息,拿到uri
# 拿到第一大块
header_list = str(data, encoding='utf-8').split('\r\n\r\n')[0]
# print('收到的信息2', header_list[0])

# 拿到第一大块的第一行
content_list = header_list.split('\r\n')[0] # GET / HTTP/1.1
# print(content_list)

uri = content_list.split(' ')[1] # /
# print(uri)

func_name = None
for key in routes:
if uri in key:
func_name = key[1]
break
if func_name:
res = func_name()
else:
res = bytes('404 not found', encoding='utf-7')


conn.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='utf-8')) # \r\n的斜杠不要写反了
conn.send(res)
conn.close()


if __name__ == '__main__':
run()



4.响应一个动态文件给浏览客户端: fn2
import socket

import time


def fn1():
# return bytes('this is xxx', encoding='utf-8')
fp = open('index_3.html', 'r', encoding='utf-8')
data = fp.read()
return bytes(data, encoding='utf-8') # 响应一个html文件给浏览客户端

def fn2():
# return bytes('this is index', encoding='utf-8')
ctime = str(time.time())
fp = open('article_4.html', 'r', encoding='utf-8')
data = fp.read()
res = data.replace('@@content@@', ctime)
return bytes(res, encoding='utf-8')



def fn3():
return bytes('this is kkk', encoding='utf-8')

routes = [
('/xxx', fn1),
('/index', fn2),
('/kkk', fn3)
]




def run():
sk = socket.socket()
sk.bind(('127.0.0.1', 8989))
sk.listen(5)

while True:
conn, addr = sk.accept()
data = conn.recv(8096)
# print('收到的信息1', data)

# 拆分请求信息,拿到uri
# 拿到第一大块
header_list = str(data, encoding='utf-8').split('\r\n\r\n')[0]
# print('收到的信息2', header_list[0])

# 拿到第一大块的第一行
content_list = header_list.split('\r\n')[0] # GET / HTTP/1.1
# print(content_list)

uri = content_list.split(' ')[1] # /
# print(uri)

func_name = None
for key in routes:
if uri in key:
func_name = key[1]
break
if func_name:
res = func_name()
else:
res = bytes('404 not found', encoding='utf-7')


conn.send(bytes('HTTP/1.1 200 OK\r\n\r\n', encoding='utf-8')) # \r\n的斜杠不要写反了
conn.send(res)
conn.close()


if __name__ == '__main__':
run()


5.响应数据库内容
模板渲染
需要将html代码和mysql结果融合

def fn3():
# 通过pymysql拿到数据库中数据
# return bytes('this is kkk', encoding='utf-8')
import pymysql
conn = pymysql.connect(host='127.0.0.1', user='root', password='999', db='db4', charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = 'select id, name, extra, type_id from user'
cursor.execute(sql)
res = cursor.fetchall()
print(res)
# [{'id': 1, 'name': 'egon', 'extra': '', 'type_id': 1},
# {'id': 2, 'name': 'jerry', 'extra': '', 'type_id': 2},]

# 将html代码和mysql结果融合
# 将该数据写入表格,替换

# 拼接
str_list = []
for user in res:
res_str = '<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>' % (user['id'], user['name'], user['extra'], user['type_id'],)
str_list.append(res_str)
s = ''.join(str_list)

# 替换
fp = open('content_5.html', 'r', encoding='utf-8')
data = fp.read()
res = data.replace('@@content@@', s)
return bytes(res, encoding='utf-8')

 6.server_jinjia表单

def fn4():
import pymysql
conn = pymysql.connect(host='127.0.0.1', user='root', password='999', db='db4', charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = 'select id, name, extra, type_id from user'
cursor.execute(sql)
users = cursor.fetchall()

fp = open('contentjinja2_5.html', 'r', encoding='utf-8')
data = fp.read()

from jinja2 import Template
template = Template(data)
data = template.render(users=users)

 

 

Django的基础

 

web请求流程

所有的web应用本质上就是一个socket服务端,用户的浏览器就是一个socket客户端,即b/s架构,基于http协议,工作在应用层.

http协议

Hyper Text Transfer Protocol,超文本传输协议,是一种建立在TCP上的无状态,一次性连接.它限制每次连接只处理一个请求,当服务器返回本次请求的应答后便立即关闭连接,下次请求再重新建立连接。

1.客户端和服务器建立连接,

2.客户端发送一个HTTP请求,说明想要访问的资源和请求的动作,

3.服务端收到请求之后,服务端开始处理请求,并根据请求做出相应的动作访问服务器资源,最后通过发送HTTP响应把结果返回给客户端

4.客户端与服务器关闭连接

其中一个请求的开始到一个响应的结束称为事务,当一个事物结束后还会在服务端添加一条日志条目。

 

DNS工作流程

DNS协议:域名系统,域名和ip地址相互映射的一个分布式数据库(基于udp协议).

工作流程:

1.打开浏览器,输入网址,客户端发送请求.

2.收到请求后,先在本地DNS服务器缓存中查找有没有这条记录.如果有该纪录项,则本地的域名服务器就直接把查询的结果返回。

3.没有,就去根域名服务器中找域名中的顶级域名(.com, .net, .cn, .org),将顶级域名中的服务器地址返回给本地DNS服务器.

4.本地服务器拿到顶级域名服务器地址后,,给顶级域名服务器发送请求,顶级域名服务器查询域名对应的ip地址.

5.顶级域名服务器将请求中的二级域名信息返回给本地服务器

6.本地服务器拿到信息后,给二级域名发送请求.二级域名服务器查询域名对应的ip地址.

7.二级域名服务器将查找到的返回给本地DNS服务器

8.本地服务器将拿到的结果缓存在自己的服务器中,以便下次查找,同时将结果返回给客户端.

 

本地DNS的查找:

C: --> Windoes -->System32 --> drivers --> etc --> hosts

当在浏览器输入url,按下回车时,到返回页面,描述过程.

收到请求后,先在dns系统中查找域名所对应的ip地址,然后dns系统将查找到的ip地址返回给浏览器,浏览器拿到ip地址后,给ip相对应的服务器发送请求.

自定义web框架

import socket

server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
   connect,addr = server.accept()
   buf = connect.recv(1024)

   connect.send(bytes('HTTP1.1 200 OK\r\n\r\n', encoding='utf-8'))
   connect.send(bytes('hello world', encoding=('utf-8')))

   connect.close()
Http协议:

得到的数据

        请求头:
GET / HTTP/1.1
Host: 127.0.0.1:8080   (主机名)
Connection: keep-alive (保持链接)
Cache-Control: max-age=0 (缓存不失效)
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Token:  bdsjalbdjsalbdjsa
请求体:
bdsabdjsabjddas

响应头:
HTTP/1.1 200 OK

响应体:
自己看到的内容
       http:  默认端口是80
       Https: 默认的端口是443

状态码
1XX:通知
2XX: 成功   200 (ok)
3XX 重定向    302(Found) 304(Not Modified)
4XX:客户端错误  403(forbidden 禁止访问)   404(not found)
5XX 服务端错误    500 (服务端代码错误) 502 (网关错误 bad gateway)
posted @ 2019-07-09 22:11  胖啊  阅读(279)  评论(0编辑  收藏  举报