这篇博客主要是实现一个简单的网页静态服务器,只显示固定的页面
那么在写web服务器之前,需要先准备以个HTML文件用来测试
写一个简单的html页面 ,用来响应给客户端—–>index.html和服务器py文件放在同一个目录中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world</title> </head> <body> <h1>Hello World</h1> </body> </html>
虽然很low,很简单 但无所谓,毕竟它只是用来辅助我们实现服务器的。
接下来进入正题!!!!创建服务器
那么首先需要理清思路,创建一个服务器需要几步
a)创建TCP套接字
b)接收客户端的请求信息
c)根据客户端不同的请求 响应给客户端对应的信息1)创建套接字:
from socket import * def my_server(): # 1.创建套接字 tcp_server = socket(AF_INET, SOCK_STREAM) # 2.绑定端口号 tcp_server.bind(('', 7788)) # 3.接收客户端的连接请求 tcp_server.listen(True) # 4.因为后续我们接收客户端请求时需要使用服务器的套接字, # 所以将它return return tcp_server
2)接收客户端请求信息
# 将服务器作为参数拿过来 def run_server(server): # 因为我们的服务器需要无休止的接收客户端的信息,所以用一个死循环 while True: # 提取一个客户端 client, address = server.accept() # 对连接成功的客户端的地址做一个输出,测试是否可以被连接 print(address) # 接收客户端的请求信息 # decode() 因为数据传输中是bytes类型,所以我们需要将它转换成字符串类型 data = client.recv(4069).decode() # 打印接收到的数据 print(data)
其实写到这里我们已经基本实现了一个可以接受到客户端请求的服务器了。 运行py程序 打开Chrom浏览器------->输入http://127.0.0.1:7788/index.html
浏览器向服务器请求index.html页面 http://127.0.0.1:7788/index.html 传输协议为HTTP协议 127.0.0.1 服务器IP地址 :7788 服务器端口号 / 客户端要请求的文件
网页是没有任何显示的,我们看程序中输出的信息
第一行的信息我们只是为了检验是否有客户端连接成功
剩下部分的客户端请求信息才是我们需要的 也就是请求头信息
那么这次我们只需要对起始行分析GET /index.html HTTP/1.1 GET:客户端请求的方式 /index.html:客户端请求的文件 HTTP/1.1:HTTP协议的版本
那么目前我们只需要拿到/index.html 这个字段,在服务器目录中找到index.html这个文件进行读取,并响应给客户端 所以需要对客户端的请求头做处理
3)对客户端的请求进行处理,并响应相应的数据
def client_handle(client, data): # 将请求头分割,取第0个下标的,也就是起始行 head_lines = data.splitlines()[0] # 用正则提取起始行中我们需要的部分,也就是客户端请求的文件 # 得到的就是/index.html file_name = re.match(r"[^/]+(/[^ ]*)", head_lines).group(1) # 读取客户端请求的文件 ./index.html 并且用二进制 with open("." + file_name, 'rb') as f: response_body = f.read()
那么上面一步,我们已经拿到了客户端想要的数据 下面将数据响应回去
def client_handle(client, data): # 将请求头分割,取第0个下标的,也就是起始行 head_lines = data.splitlines()[0] # 用正则提取起始行中我们需要的部分,也就是客户端请求的文件 # 得到的就是/index.html file_name = re.match(r"[^/]+(/[^ ]*)", head_lines).group(1) # 读取客户端请求的文件 ./index.html 并且用二进制 with open("." + file_name, 'rb') as f: response_body = f.read() # 创建一个响应头 response_headers = "HTTP/1.1 200 OK\r\n" # 添加空行 response_headers += "\r\n" # 将响应头 空行 响应体组合起来 content = response_headers.encode() + response_body # 发送给客户端 client.send(content)
一个简单的静态服务器完成,下面是完整的代码:
from socket import *
import re
def my_server():
# 1.创建套接字
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 2.绑定端口号
tcp_server.bind(('', 7788))
# 3.接收客户端的连接请求
tcp_server.listen(True)
return tcp_server
def client_handle(client, data):
# 将请求头分割,取第0个下标的,也就是起始行
head_lines = data.splitlines()[0]
# 用正则提取起始行中我们需要的部分,也就是客户端请求的文件
# 得到的就是/index.html
file_name = re.match(r"[^/]+(/[^ ]*)", head_lines).group(1)
# 读取客户端请求的文件 ./index.html 并且用二进制
with open("." + file_name, 'rb') as f:
response_body = f.read()
# 创建一个响应头
response_headers = "HTTP/1.1 200 OK\r\n"
# 添加空行
response_headers += "\r\n"
# 将响应头 空行 响应体组合起来
content = response_headers.encode() + response_body
# 发送给客户端
client.send(content)
# 数据发送好之后,关闭客户端
client.close()
def run_server(server):
while True:
# 提取一个客户端关联套接字
client, address = server.accept()
#
print(address)
# 接收客户端的请求信息
data = client.recv(4069).decode()
print(data)
client_handle(client, data)
if __name__ == '__main__':
server = my_server()
run_server(server)