推荐文章:
Liunx系列:
2、Linux进阶命令 任务编程系列:
网络编程:
1、网络编程
HTTP协议
1、HTTP协议介绍
HTTP协议全程是超文本传输协议。
超文本是超级文本的缩写,是指超越文本限制或者超链接,比如:图片、音乐、视频、超链接等等都属于超文本。
HTTP协议设计之前目的是传输网页数据的,现在允许传输任意类型的数据。
传输HTTP协议格式的数据时给予TCP传输协议的,发送数据之前需要先建立连接。
2、HTTP协议的作用
它规定了浏览器和Web服务器通信数据的格式,也就是说浏览器和Web服务器通信需要使用http协议。
3、浏览器访问web服务器的通信过程
通信效果图:
4、小结
UPL
1、URL的概念
URL表达的意思是统一资源定位符,通俗理解就是网络资源地址,也就是我们常说的网址。
2、URL的组成
URL的样子:
https://news.163.com/18/1122/10/E178J2O4000189FH.html
URL的组成部分:
域名:
域名就是IP地址的别名,它是用点进行分割使用英文字母和数字组成的名字,使用域名目的就是方便的记住某台主机IP地址。
URL的扩展:
https://news.163.com/hello.html?page=1&count=10
参数说明:
3、小结
查看HTTP协议的通信过程
1、谷歌浏览器开发者工具的使用
首先需要安装Google Chrome浏览器,然后WIndows和Linux平台按F12调出开发者工具,Mac OS选择 视图 -> 开发者 -> 开发者工具或者直接使用alt + command + i这个快捷键,还有一个多平台通用的操作就是网页右击选择检查。
开发者工具的效果图:
2、总结
HTTP请求报文
1、HTTP请求报文介绍
HTTP最常见的请求报文有两种:
说明:
2、HTTP GET 请求报文分析
HTTP GET 请求报文效果图:
3、HTTP POST 请求报文分析
HTTP POST 请求报文效果图:
4、小结
HTTP响应报文
Web服务器程序发送给浏览器的http协议的数据
1、HTTP响应报文分析
2、HTTP状态码
HTTP状态码是用于表示web服务器响应状态的3位数字代码。
状态码 | 说明 |
---|---|
200 | 请求成功 |
307 | 重定向 |
400 | 错误的请求,请求地址或者参数有误 |
404 | 请求资源在服务器不存在 |
500 | 服务器内部源代码出现错误 |
3、小结
搭建Python自带静态Web服务器
1、静态Web服务器是什么?
可以为发出请求的浏览器提供静态文档的程序。
平时我们浏览百度新闻数据的时候,每天的新闻数据都会发生变化,那访问的这个页面就是动态的,而我们开发的是静态的,页面的数据补水发生变化。
2、如何搭建Python自带的静态Web服务器
搭建Python自带的静态Web服务器使用python3 -m http.server 端口号,效果图如下:
-m选项说明:
-m表示允许包里面的模块,执行这个命令的时候,需要进入你自己指定静态文件的目录,然后通过浏览器就能访问对应的html文件了,这样一个静态的web服务器就搭建好了。
注意:
执行该命令之前一定要切换到指定资源目录里面
执行效果:
5、小结
静态Web服务器 - 返回固定页面数据
1、开发自己的静态Web服务器
实现步骤:
2、静态Web服务器 - 返回固定页面数据的示例代码
import socket
import os
def main():
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 循环等待接受客户端的连接请求
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
except Exception as e:
# 代码执行到此,说明没有请求的该文件,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 读取404页面数据
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
else:
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
finally:
# 关闭服务于客户端的套接字
new_socket.close()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
3、静态Web服务器 - 返回指定页面数据的示例代码
import socket
import os
def main():
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 循环等待接受客户端的连接请求
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
# 关闭服务于客户端的套接字
new_socket.close()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
4、静态Web服务器 - 返回404页面数据的示例代码
import socket
import os
def main():
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 循环等待接受客户端的连接请求
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
except Exception as e:
# 代码执行到此,说明没有请求的该文件,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 读取404页面数据
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
else:
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
finally:
# 关闭服务于客户端的套接字
new_socket.close()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
静态Web服务器 - 多任务版
1、静态Web服务器的问题
目前的Web服务器,不能支持多用户同时访问,只能一个一个的处理客户端的请求,那么如何开发多任务版的Web服务器同时处理多个客户端的请求?
可以使用多线程,比进程更加节省内存资源。
多任务版web服务器程序的实现步骤:
2、静态Web服务器 - 多任务版的示例代码
# -*- codeing = utf-8 -*-
# @Time : 2021/12/11 1:23 下午
# @Author : 李明辉
# @File : ithui_静态web服务器多任务版.py
# @Software : PyCharm
import socket
import os
import threading
# 处理客户端请求
def handle_client_requst(new_socket):
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
except Exception as e:
# 代码执行到此,说明没有请求的该文件,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 读取404页面数据
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
else:
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
finally:
# 关闭服务于客户端的套接字
new_socket.close()
def main():
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 循环等待接受客户端的连接请求
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
sub_thread = threading.Thread(target=handle_client_requst, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
静态Web服务器 - 面向对象开发
1、以面向对象的方式开发静态Web服务器
实现步骤:
2、静态Web服务器 - 面向对象开发的示例代码:
# -*- codeing = utf-8 -*-
# @Time : 2021/12/11 1:45 下午
# @Author : 李明辉
# @File : ithui_静态web服务器面向对象.py
# @Software : PyCharm
import socket
import threading
# http协议的web服务器类
class HTTPWebServer(object):
def __init__(self):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 把tcp服务端的套接字作为web服务器对象的属性
self.tcp_server_socket = tcp_server_socket
# 处理客户端请求
@staticmethod
def handle_client_requst(new_socket):
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
except Exception as e:
# 代码执行到此,说明没有请求的该文件,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 读取404页面数据
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
else:
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
finally:
# 关闭服务于客户端的套接字
new_socket.close()
# 启动服务器的方法
def start(self):
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = self.tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
sub_thread = threading.Thread(target=self.handle_client_requst, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
def main():
# 创建一个web服务器
web_server = HTTPWebServer()
# 启动服务器
web_server.start()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
3、小结
1、把提供服务的web服务器抽象成为一个类(HTTPWebServer)
class HTTPWebServer(object):
2、提供Web服务器的初始化方法,在初始化方法里面创建socket对象
def __init__(self):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 8000))
# 设置监听
tcp_server_socket.listen(128)
# 把tcp服务端的套接字作为web服务器对象的属性
self.tcp_server_socket = tcp_server_socket
3、提供一个开启Web服务器的方法,让Web服务器处理客户端请求
def start(self):
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = self.tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
sub_thread = threading.Thread(target=self.handle_client_requst, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
静态Web服务器 - 命令行启动动态绑定端口号
1、开启命令行启动动态绑定端口号的静态web服务器
实现步骤:
2、静态web服务器命令行启动动态绑定端口号代码示例:
# -*- codeing = utf-8 -*-
# @Time : 2021/12/11 2:18 下午
# @Author : 李明辉
# @File : ithui_终端命令行启动绑定端口号.py
# @Software : PyCharm
import socket
import threading
import sys
# http协议的web服务器类
class HTTPWebServer(object):
def __init__(self, port):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", port))
# 设置监听
tcp_server_socket.listen(128)
# 把tcp服务端的套接字作为web服务器对象的属性
self.tcp_server_socket = tcp_server_socket
# 处理客户端请求
@staticmethod
def handle_client_requst(new_socket):
# 接收客户端的请求信息
recv_data = new_socket.recv(4096)
# 判断接收的数据长度是否为0
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制数据进行解码
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 对数据按照空格进行分割
request_list = recv_content.split(" ", maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
print(request_path)
# 判断请求的是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打开文件读取文件中的数据, 提示:这里使用rb模式,兼容打开图片文件
with open("static" + request_path, "rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
# 提示:with open 关闭文件这步操作不用程序员来完成,系统帮我们来完成
except Exception as e:
# 代码执行到此,说明没有请求的该文件,返回404状态信息
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 读取404页面数据
with open("static/error.html", "rb") as file:
file_data = file.read()
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
else:
# 代码执行到此,说明文件存在,返回200状态信息
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS/1.0\r\n"
# 响应体
response_body = file_data
# 把数据封装成http 响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 发送给浏览器的响应报文数据
new_socket.send(response)
finally:
# 关闭服务于客户端的套接字
new_socket.close()
# 启动服务器的方法
def start(self):
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = self.tcp_server_socket.accept()
# 代码执行到此,说明连接建立成功
sub_thread = threading.Thread(target=self.handle_client_requst, args=(new_socket,))
# 设置成为守护主线程
sub_thread.setDaemon(True)
# 启动子线程执行对应的任务
sub_thread.start()
def main():
# 获取终端命令行参数
params = sys.argv
if len(params) != 2:
print('执行的命令格式如下:python3 xxx.py 9000')
return
# 判断第二个参数是否都是由数字组成的字符串
if not params[1].isdigit():
print('执行的命令格式如下:python3 xxx.py 9000')
return
# 代码执行到此,说明命令行参数的个数一定2个并且第二个参数是由数字组成的字符串
port = params[1]
# 创建一个web服务器
web_server = HTTPWebServer(port)
# 启动服务器
web_server.start()
# 判断是否是主模块的代码
if __name__ == '__main__':
main()
END