# web静态服务器实现
web静态服务器实现,可以通过浏览器访问
##返回指定页面数据
"""返回指定页面数据"""
from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
import re
def main():
# 创建tcp服务端套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
# 设置socket选项,立即释放端口,正常情况下,服务器断开连接后,需要1-2分钟才会释放端口
tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
# 局域网下其他电脑可以通过 本机ip:9090访问,本机可以使用127.0.0.1:9090访问(默认是80,所以后面要加端口号)
tcp_server.bind(("", 9090))
# 设置监听:单任务,同一时刻只有一个客户端能建立连接,其他的都等着建立连接
tcp_server.listen(128)
# 循环接受可客户端的连接请求
while True:
# 生成一个新的套接字,专门处理这一个客户端,tcp_server就可以省下来等待其他的客户端请求
service_client_sock, ip_port = tcp_server.accept()
# 正常请求报文1024就足够接收了,为了防止特殊情况使用了4096
client_request_data = service_client_sock.recv(4096)
client_request_content = client_request_data.decode("utf-8")
# 查找请求资源路径
print(client_request_content)
match_obj = re.search("r/\S*", client_request_content)
print(match_obj)
if not match_obj:
print("访问路径有误")
service_client_sock.close()
return
request_path = match_obj.group()
print(request_path)
if request_path == "/":
request_path = "/index.html"
# 判断访问的资源存在可以使用异常处理或者os模块的os.path.exists()
# import os
# os.chdir("static")
# res = os.path.exists('index.html')
# print(res)
try:
with open("static" + request_path, 'rb') as file:
file_data = file.read()
except Exception as e:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体 -> 打开一个404html数据把数据给浏览器
response_body = "<h1>非常抱歉,您当前访问的网页已经不存在了</h1>".encode("utf-8")
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_sock.send(response_data)
else:
# 准备响应数据
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent_Type: text/html; charset=utr-8\r\n"
# 响应体
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
service_client_sock.send(response_data)
finally:
service_client_sock.close()
if __name__ == "__main__":
main()
##使用协程完成多任务web服务
"""
使用协程完成多任务web服务器,节省资源,效率比较高
gevent开辟协程如果程序一直运行则不需要加上join操作,因为程序没有退出
这程序我没有使用,from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
因为主程序中使用socket,它识别不出来是那个socket
"""
import socket
import re
import gevent
from gevent import monkey
# 让gevent能够识别耗时操作,让协程自动切换执行,失败的耗时操作由: recv, accept, time.sleep, 网络请求延时
monkey.patch_all()
# 处理客户端的请求
def handle_client_request(service_client_socket):
# 获取客户端的请求报文数据
client_request_data = service_client_socket.recv(4096)
print(client_request_data)
# GET /index2.html HTTP/1.1xxxxxxx
client_request_conent = client_request_data.decode("utf-8")
# 通过正则查找请求的资源路径
match_obj = re.search("/\S*", client_request_conent)
if not match_obj:
print("访问路径有误")
service_client_socket.close()
return
# 获取匹配结果
request_path = match_obj.group()
print(request_path)
if request_path == "/":
# 如果用户没有指定资源路径那么默认访问的数据是首页的数据
request_path = "/index.html"
# 读取指定文件数据
# 使用rb的原因是浏览器也有可能请求的是图片
try:
with open("static" + request_path, "rb") as file:
# 读取文件数据
file_data = file.read()
except Exception as e:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体 -> 打开一个404html数据把数据给浏览器
response_body = "<h1>非常抱歉,您当前访问的网页已经不存在了</h1>".encode("utf-8")
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
else:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体
response_body = file_data
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
finally:
service_client_socket.close()
def main():
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置socket选项,立即释放端口
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 9090))
# 设置监听
tcp_server_socket.listen(128)
# 循环接收客户端的连接请求
while True:
service_client_socket, ip_port = tcp_server_socket.accept()
# handle_client_request(service_client_socket)
# 开辟协程并执行对应的任务
gevent.spawn(handle_client_request, service_client_socket)
# 不需要加上join,主要原有是我们的进程不会退出
# g1.join()
if __name__ == '__main__':
main()
使用面向对象的方式实现web静态服务器
"面向对象服务器开发"
import socket
import re
import gevent
from gevent import monkey
# 让gevent能够识别耗时操作,让协程自动切换执行,失败的耗时操作由: recv, accept, time.sleep, 网络请求延时
monkey.patch_all()
class HttpWebServer(object):
def __init__(self):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置socket选项,立即释放端口
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", 9090))
# 设置监听
tcp_server_socket.listen(128)
self.tcp_server_socket = tcp_server_socket
@staticmethod
def handle_client_request(service_client_socket):
# 获取客户端的请求报文数据
client_request_data = service_client_socket.recv(4096)
print(client_request_data)
# GET /index2.html HTTP/1.1xxxxxxx
client_request_conent = client_request_data.decode("utf-8")
# 通过正则查找请求的资源路径
match_obj = re.search("/\S*", client_request_conent)
if not match_obj:
print("访问路径有误")
service_client_socket.close()
return
# 获取匹配结果
request_path = match_obj.group()
print(request_path)
if request_path == "/":
# 如果用户没有指定资源路径那么默认访问的数据是首页的数据
request_path = "/index.html"
# 读取指定文件数据
# 使用rb的原因是浏览器也有可能请求的是图片
try:
with open("static" + request_path, "rb") as file:
# 读取文件数据
file_data = file.read()
except Exception as e:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体 -> 打开一个404html数据把数据给浏览器
response_body = "<h1>非常抱歉,您当前访问的网页已经不存在了</h1>".encode("utf-8")
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
else:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体
response_body = file_data
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
finally:
service_client_socket.close()
def start(self):
# 循环接收客户端的连接请求
while True:
service_client_socket, ip_port = self.tcp_server_socket.accept()
# handle_client_request(service_client_socket)
# 开辟协程并执行对应的任务
gevent.spawn(self.handle_client_request, service_client_socket)
# 不需要加上join,主要原有是我们的进程不会退出
# g1.join()
def main():
server = HttpWebServer()
server.start()
if __name__ == '__main__':
main()
通过命令行启动服务器,可以自动设置端口号
import sys
import socket
import re
import gevent
from gevent import monkey
# 让gevent能够识别耗时操作,让协程自动切换执行,失败的耗时操作由: recv, accept, time.sleep, 网络请求延时
monkey.patch_all()
class HttpWebServer(object):
def __init__(self, port):
# 创建tcp服务端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置socket选项,立即释放端口
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口号
tcp_server_socket.bind(("", port))
# 设置监听
tcp_server_socket.listen(128)
self.tcp_server_socket = tcp_server_socket
@staticmethod
def handle_client_request(service_client_socket):
# 获取客户端的请求报文数据
client_request_data = service_client_socket.recv(4096)
print(client_request_data)
# GET /index2.html HTTP/1.1xxxxxxx
client_request_conent = client_request_data.decode("utf-8")
# 通过正则查找请求的资源路径
match_obj = re.search("/\S*", client_request_conent)
if not match_obj:
print("访问路径有误")
service_client_socket.close()
return
# 获取匹配结果
request_path = match_obj.group()
print(request_path)
if request_path == "/":
# 如果用户没有指定资源路径那么默认访问的数据是首页的数据
request_path = "/index.html"
# 读取指定文件数据
# 使用rb的原因是浏览器也有可能请求的是图片
try:
with open("static" + request_path, "rb") as file:
# 读取文件数据
file_data = file.read()
except Exception as e:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体 -> 打开一个404html数据把数据给浏览器
response_body = "<h1>非常抱歉,您当前访问的网页已经不存在了</h1>".encode("utf-8")
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
else:
# 准备响应报文数据
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server: PWS1.0\r\nContent-Type: text/html;charset=utf-8\r\n"
# 响应体
response_body = file_data
# 匹配响应报文数据
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 发送响应报文数据
service_client_socket.send(response_data)
finally:
service_client_socket.close()
def start(self):
# 循环接收客户端的连接请求
while True:
service_client_socket, ip_port = self.tcp_server_socket.accept()
# handle_client_request(service_client_socket)
# 开辟协程并执行对应的任务
gevent.spawn(self.handle_client_request, service_client_socket)
# 不需要加上join,主要原有是我们的进程不会退出
# g1.join()
def main():
print(sys.argv)
# 端口号可以自定义
if len(sys.argv) != 2:
print("启动命令如下: python3 command_parameter_server.py 9090")
return
if not sys.argv[1].isdigit():
print("启动命令如下: python3 command_parameter_server.py 9090")
return
port = int(sys.argv[1])
print(port)
server = HttpWebServer(port)
server.start()
if __name__ == '__main__':
main()
最后一个程序的运行已及一个界面的截图