Python高级
-03-web服务器
一、http协议
1、简介:客户端与服务器通信的一种规范(也叫超文本传输协议)
2、简述协议规范
(1)浏览器 --向-》服务器发送请求格式如下:
GET /sugrec/.. HTTP/1.1
Host: www.baidu.com
Connection: keep-alive.....
Accept: application/json, ....
User-Agent: Mozilla/5.0......
Referer: https://www.baidu.com/?tn=40020637_12_oem_dg
Cookie: BIDUPS........
空行
请求体
图示:get请求一般没有请求体
get | 用于读取操作,请求参数直接拼接到URL后面(浏览器对URL参数长度有限制) |
post | 常用于添加、修改、删除操作,请求参数可以放到请求体中(没有大小限制) |
Host | 服务器的域名端口号 |
Connection | 该浏览器想要使用的连接类型 |
User-Agent | 浏览器身份标识 |
Referer | 表示浏览器所访问的上一个页面 |
Cookie | 之前由服务器设置set-Cookie发送的Cookie |
Data | 发送该消息的时间和日期 |
Content-Type | 请求的类型 |
Content-Length | 请求体的长度(以字节为单位) |
Accept | 能够接受响应的类型 |
Accept-Charset | 能够接受的字符集 |
Accept-Encoding | 能够接受的编码方式 |
Accept-Langue | 能够接受响应内容的自然语言 |
(2)服务器 --向-》浏览器回送数据格式如下:
HTTP/1.1 200 OK
Content-Length: 760
Content-Type: text/plain; charset=UTF-8
Date: Thu, 22 Jul 2021 10:15:04 GMT
空行
请求体
图示:
Content-Length | 响应体的长度(字节为单位) |
Content-Type | 响应的类型 |
Date | 发送该消息的时间 |
Sever | 服务器名字 |
Last-Modified | 所请求的对象最后修改时间 |
Set-Cookie | 返回一个Cookie让浏览器去保存 |
状态码范围 | 含义 |
100-199 | 信息响应 |
200-299 | 成功响应 |
300-399 | 重定向 |
400-599 | 客户端错误 |
500-699 | 服务器错误 |
状态码 | 短语 | 含义 |
100 | Continue | |
200 | OK | 请求成功 |
302 | Found | 重定向 |
304 | Not Modified | 使用缓存数据 |
400 | Bad Request | |
401 | Unauthorized | |
403 | Forbidden | |
404 | Not Found | 服务器无法找到资源 |
405 | Method Not Allowed | |
408 | Request Timeout | |
500 | Internal Server Error | 服务器出现错误 |
注: "\r\n" 浏览器换行表示
3、python实现简单web服务器
使用模块:socket模块:用于接收请求,发送响应,re模块:用于处理请求
本机的IP:127.0.0.1 (主要用于测试,或者写localhost)
根据http协议发送给浏览器的数据由三部分组成:
响应求行+头:至少有
http/1.1 200 ok
空行:"\r\n" 表示换行
响应体(如:html页面)
main()函数思路:
创建socket,绑定IP、端口,被动监听,等待客户端(浏览器)连接收发数据
接收请求信息(请求信息为空,代表客户端关闭,此时关闭该socket)
处理请求信息
根据请求信息查找资源
发送资源
import socket
import threading
def get_msg(b):
s = b.decode("utf-8")
s_list = s.split()
path = s_list[1][1:]
if not s_list[1][1:]:
path = "login.html"
return "htmls/" + path
def recv_send(new_socket):
#长链接
while True:
#接收信息
recv = new_socket.recv(1024)
#接收信息为空,表示客户端断开了连接
if not recv:
print("一个客户端断开了连接")
new_socket.close()
break
else:
# 处理信息,获取请求的文件路径
s_path = get_msg(recv)
try:
print("获取资源:%s" % s_path)
with open(s_path, "rb") as f:
content = f.read()
head = "HTTP/1.1 200 ok\r\n"
#告诉浏览器资源长度,防止一直打圈
head += "Content-Length:%d\r\n" % len(content)
head += "\r\n"
b_head = head.encode("utf-8")
resp_msg = b_head + content
new_socket.send(resp_msg)
#出现异常说明资源未找到
except:
head = "HTTP/1.1 404 NOT FOUND\r\n"
head += "\r\n"
content = head + "资源路径有误"
new_socket.send(content.encode("utf-8"))
print("未找到资源:%s" % s_path)
def main():
#创建socket,绑定,被动,等待连接
s_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_socket.bind(("127.0.0.1", 7788))
s_socket.listen(128)
while True:
new_socket, addr = s_socket.accept()
#多线程完成响应
t = threading.Thread(target=recv_send, args=(new_socket,))
t.start()
if __name__ == "__main__":
main()
#运行结果
web静态服务器-多任务实现方式:
多进程:主进程和子进程都要关闭连接(进程复制资源)
多线程:子进程中关闭连接(资源共享)
gevent协程:
设置socket为非堵塞方式:xx_socket.setblocking(False),即:该socket不会因为accept(),recv()堵塞,如果accpt(),没有新客户端到来,产生异常,如果recv(),没有受到消息,产生异常,通过异常处理,判断是否有新客户端到来,通过异常处理,判断是否有新消息
epoll:
原理,共享内存,事件通知方式
Linux操作系统中才能使用:Linux系统适合做服务器,windows操作系统桌面程序
epoll实现步骤:
(1)创建epoll对象
import select
epl = select.epoll()(2)将监听socket对应的fd注册到epoll中
epl.register(tcp_server_socket.fileno(), select.EPOLLIN)
(3)默认堵塞,直到os检测到数据到来,通过数据监听的方式,告诉程序,此时才会解堵塞
fd_event_list = epl.poll()
返回值:[(fd, event), (socket对应文件描述符, 这个文件描述符是什么事件)]
4、短连接、长连接
短连接:http/1.0
长连接:http/1.1
如果:写的代码虽然是http/1.1,但是每次发送完数据就关闭了socket,固每次请求都要进行三次握手、四次挥手,其实这就是短连接、
注:Content-Length:告诉客户端,发送的数据有多大。即:告诉客户端接收到多少数据,表示服务器数据发送完毕,防止浏览器一直打圈。
二、TCP/IP协议族(指的是上百种协议的总和)
1、各个协议之间的关系图
分类:应用层、传输层、网络层、链路层
例:TCP/IP传输示意图
2、另外一套标准
三、网络通信
1、IP地址、子网掩码
IP地址种类不同的,而确定种类的就是子网掩码
IP与子网掩码,按照二进制做按位与操作(按位都是1则为1,否则为0)
不为0部分为网络号,为0部分为主机号
两台电脑通过网线通信
1、如果两台电脑之间通过网线连接是可以直接通信的,但是需要提前设置好IP地址以及网络掩码
2、IP地址需要控制在同一网段内,例:192.168.1.1另一台为192.168.1.2,则可以进行通信
2、交换机示意图
实际地址(MAC地址),即网卡的序列号(唯一的)
3、路由器示意图(网关)
默认网关:网关-具有转发数据功能的设备,一般是路由器
从一个网络发送到另一个网络,需要通过路由器,传输过程IP不变,mac在发生变化
4、DNS服务器