1.复习网络层级
应用层、传输层、网络层、链路层 可以把后三者看为一个整体(快递公司)
应用层:解决要传递什么数据
传输层:解决如何传输数据 udp tcp 可以理解为快递公司
网络层:标识地理位置 坐标--ip
链路层:真是的 具体的传输工具 (汽车、飞机)
四者不一定同时用到 但是 后三者一定会用到
socket是用来解决传输层以下的部分
对于应用层来说 在socket.send() 过程中用到 的数据
应用层:ftp ssh smtp Pop3 http......等
2.http协议 超文本传输协议
http请求方式(用户想要服务器执行什么应为):
GET 客户端请求资源 获取数据
POST 修改数据
PUT 保存数据
DELETE 删除数据
OPTION 询问服务器的 某种支持特性
HEAD返回报文头
百度为例:F12 network→Headers: requests Headers 查看
客户端发送(请求):(socket.send( ))
分为 起始行 请求头 请求体
GET:请求方式 /:内容
如果 需要上传图片(例:保存头像)在上图下面 (body 请求体)
Content-Length:128
\r\n
01010100011010 图片
username:abc
password:123
服务器发送(响应)拿到客户端报文解析(soket.recv()) 后(socket.send())响应体
第一行 200是响应值 状态码2开头 成功 3开头需要跳转 4开头用户端 错误 5开头服务器错误
(每一行都是\r\n换行)
3.自己构造 服务器 可链接
from socket import *
from multiprocessing import Process
def deal_data(client_socket,addr):
request_data = client_socket.recv(1024)
print(request_data)
response_start_line = "HTTP/1.1 200 OK\r\n"
response_headers = "Sever: My server\r\n"
response_body = "hello"
response = response_start_line + response_headers + "\r\n" + response_body
client_socket.send(bytes(response, "utf-8"))
client_socket.close()
print("[%s:%s] 已退出" % addr)
if __name__ == '__main__':
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(("", 7777))
s.listen(128)
while True:
client_socket, addr = s.accept()
print("[%s%s]用户连接" % addr)
p = Process(target=deal_data, args=(client_socket,addr))
p.start()
client_socket.close()
from multiprocessing import Process
import re
from socket import *
HTML_ROOT_DIR = "./html"
def func(client_socket,client_addr):
# 接收客户端数据
recv_data = client_socket.recv(1024)
print("%s:%s" % (client_socket,recv_data))
request_lines = recv_data.splitlines()
# 解析客户端请求
request_start_line = request_lines[0]
re_file = re.match(r"\w+ +(/[^ ]*) ",request_start_line.decode("utf-8")).group(1)
# 打开文件 读取数据
try:
if "/" == re_file:
re_file = "./index.html"
file_name = HTML_ROOT_DIR+re_file
file = open(file_name,"rb")
except IOError:
response_start_line = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers = "Sever: My server\r\n"
response_body = "NOT FOUND"
else:
file_data = file.read()
file.close()
# 构造响应数据
response_start_line = "HTTP/1.1 200 OK\r\n"
response_headers = "Sever: My server\r\n"
response_body = file_data.decode("utf-8")
response = response_start_line + response_headers + "\r\n" + response_body
client_socket.send(bytes(response, "utf-8"))
client_socket.close()
print("[%s:%s] 已退出" % client_addr)
def main():
server_socket = socket(AF_INET,SOCK_STREAM)
server_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server_socket.bind(("",8000))
server_socket.listen(128)
while True:
client_socket,client_addr = server_socket.accept()
p = Process(target=func, args=(client_socket,client_addr))
p.start()
client_socket.close()
if __name__ == '__main__':
main()
以上代码面向对象封装:
from multiprocessing import Process
import re
from socket import *
HTML_ROOT_DIR = "./html"
class HTTPServer(object):
def __init__(self):
self.server_socket = socket(AF_INET, SOCK_STREAM)
self.server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
def start(self):
self.server_socket.listen(128)
while True:
client_socket, client_addr = self.server_socket.accept()
p = Process(target=self.func, args=(client_socket, client_addr))
p.start()
client_socket.close()
def func(self, client_socket, client_addr):
# 接收客户端数据
recv_data = client_socket.recv(1024)
print("%s:%s" % (client_addr, recv_data))
request_lines = recv_data.splitlines()
# 解析客户端请求
request_start_line = request_lines[0]
re_file = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
# 打开文件 读取数据
try:
if "/" == re_file:
re_file = "./index.html"
file_name = HTML_ROOT_DIR + re_file
file = open(file_name, "rb")
except IOError:
response_start_line = "HTTP/1.1 404 NOT FOUND\r\n"
response_headers = "Sever: My server\r\n"
response_body = "NOT FOUND"
else:
file_data = file.read()
file.close()
# 构造响应数据
response_start_line = "HTTP/1.1 200 OK\r\n"
response_headers = "Sever: My server\r\n"
response_body = file_data.decode("utf-8")
response = response_start_line + response_headers + "\r\n" + response_body
client_socket.send(bytes(response, "utf-8"))
client_socket.close()
print("[%s:%s] 已退出" % client_addr)
def bind(self, port=8000):
self.server_socket.bind(("", port))
def main():
httpserver = HTTPServer()
httpserver.bind()
httpserver.start()
if __name__ == '__main__':
main()
动态服务器流程图:
动态服务器主程序:!!!!
from multiprocessing import Process
import re
import sys
from socket import *
class WebServer(object):
def __init__(self,application):
# 创建套接字
self.s = socket(AF_INET,SOCK_STREAM)
self.s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
self.application = application
def bind(self, port=8000):
# 设置端口
self.s.bind(("",port))
def start_response(self, status, headers):
response_header = "HTTP /1.1" + status + "\r\n"
for header in headers:
response_header += "%s:%s\r\n" % header
self.response_header = response_header
def func(self, c_socket, c_addr):
# 接收请求
requset_data = c_socket.recv(1024)
# 1解析请求
request_lines = requset_data.splitlines()
request_start_line = request_lines[0]
file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
method = re.match(r"(\w+) +/[^ ]* ", request_start_line.decode("utf-8")).group(1)
env = {
"PATH_INFO":file_name,
"METHOD":method
}
response_body = self.application(env,self.start_response)
response = self.response_header +"\r\n" + response_body
# 发送报文
c_socket.send(bytes(response,"utf-8"))
c_socket.close()
def start(self):
# 监听
self.s.listen(128)
while True:
c_socket,c_addr = self.s.accept()
p = Process(target=self.func, args=(c_socket,c_addr))
p.start()
c_socket.close()
def main():
if len(sys.argv) < 2:
sys.exit("")
moudle_name, app = sys.argv[1].split(":")
m = __import__(moudle_name)
application = getattr(m, app)
httpserver = WebServer(application)
httpserver.bind(6666)
httpserver.start()
if __name__ == '__main__':
main()
动态服务器 应用框架:!!!!!!!
import time
STATIC_FILE_ROOT_DIR = "./html"
class Application(object):
""""""
def __init__(self,urls):
self.urls = urls
def __call__(self, env, start_response):
app_path = env.get("PATH_INFO","/")
# 静态文件
if app_path.startswith("/static"):
file_name = app_path[7:]
try:
file_path = STATIC_FILE_ROOT_DIR + file_name
f = open(file_path, "rb")
except IOError:
status = "404 NOT FOUND"
headers = []
start_response(status,headers)
return "not found"
else:
file_data = f.read()
f.close()
status = "200 OK"
headers = []
start_response(status,headers)
return file_data
# 动态文件
for url, application in self.urls:
if url == app_path:
return application(env, start_response)
status = "404 NOT FOUND"
headers = []
start_response(status, headers)
return "not found"
def show_ctime(env, start_response):
status = "200 OK"
headers = [
("Content-Type", "text/plain")
]
start_response(status, headers)
return time.ctime()
def say_hello(env, start_response):
status = "200 OK"
headers = [
("Content-Type", "text/plain")
]
start_response(status, headers)
return "hello itcast"
def say_haha(env, start_response):
status = "200 OK"
headers = [
("Content-Type", "text/plain")
]
start_response(status, headers)
return "hello haha"
urls = [
("/", show_ctime),
("/ctime", show_ctime),
("/sayhello", say_hello),
("/sayhaha", say_haha),
]
app = Application(urls)