您的位置:首页 > 理论基础 > 计算机网络

基于HTTP模拟实现静态服务器-多任务多线程

2017-12-15 21:29 405 查看
“””

根据用户访问的时候 指定的路径 服务器返回指定的页面数据

使用多进程方式实现

“””

import re

import socket

import threading

“””

a 创建一个TCP监听的套接字 接受到客户端的连接请求

b 接收客户端的请求报文

c 根据HTTP的请求报文格式进行解析

d 根据HTTP的响应报文格式进行响应

“”“

def client_handler(client_socket):
"""处理客户端请求  并且予以相应"""
# 接收客户端的HTTP请求报文 --- 数据
data = client_socket.recv(4096)

if not data:
print("客户端断开了连接")
client_socket.close()
return

# 对请求数据进行解码操作
str_data = data.decode()

# 拆分出请求报文中的每一行 解析用户的请求路径
data_list = str_data.split("\r\n")
# print(data_list)

# 获取请求行数据 第0行 GET /path/a/ab/index.html HTTP/1.1
request_line = data_list[0]
result = re.match(r"\w+\s+(\S+)", request_line)
if not result:
# 表明请求的格式不合法
client_socket.close()
return
# 格式合法  根据正则提取出用户请求的路径信息
path_info = result.group(1)
print("收到用户请求路径" + path_info)

# 当用户访问/的时候  访问的是/index.html
if path_info == '/':
# index.html一般代表一个网站的首页
path_info = '/index.html'

# HTTP响应报文格式
"""
成功 HTTP/1.1 200 OK\r\nServer: pythonserver\r\n\r\n页面数据
失败 HTTP/1.1 404 Not Found\r\nServer: pythonserver\r\n\r\n页面数据

用户页面上看到的数据 其实就是服务器本地的文件数据
"""

# 响应相关的数据 ---- 根据响应报文格式 拼接相关数据
# 响应行数据

# 服务器指定的数据目录 + 用户请求的目录
#
# static           + /index.html  /home/it/001.txt
try:
# 以二进制方式打开文件 读的文件数据就是Bytes类型
file = open("static" + path_info, "rb")
# 如果文件数据很大 则会出现隐患
file_data = file.read()
file.close()

except Exception as e:
# 如果用户请求的路径不存在 则打开文件失败
response_data = "HTTP/1.1 404 Not Found\r\n"

# 头部数据
response_data += "Server: PythonServer2.0\r\n"

# 空行
response_data += "\r\n"

# 响应体数据
response_data += "EROOR"
# response_data str---> bytes
client_socket.send(response_data.encode())
else:
# 打开文件成功
# 文件数据就是响应体数据
response_data = "HTTP/1.1 200 OK\r\n"
# 头部数据
response_data += "Server: PythonServer2.0\r\n"
# 空行
response_data += "\r\n"
response_body = file_data
response_data = response_data.encode() + response_body

client_socket.send(response_data)
finally:
# 在发生异常 或者没有发生异常的情况下 都会执行这一步
client_socket.close()

def main():
# 创建一个TCP监听的套接字 接受到客户端的连接请求
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 地址重用 在重启的时候能够立马重用相关的地址和端口 1表示设置 0表示取消设置
tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定端口
tcp_socket.bind(('', 8888))

# 将套接字设置为被动监听模式
tcp_socket.listen(128)

# 循环接收客户端请求 ---
while True:
client_socket, client_addr = tcp_socket.accept()
print("收到来自%s的连接请求" % str(client_addr))

# 在接收一个客户端请求的时候 单独创建一个子线程
# 线程是操作系统进行调度的基本单位
#  对客户端的请求  进行处理
# client_handler(client_socket)

# 一个进程内部的多个线程  共享资源 不能关闭client_socket
thd = threading.Thread(target=client_handler, args=(client_socket,))
thd.start()
# client_socket.close()

if __name__ == '__main__':
main()
# 客户端请求方式  在浏览器中输入 http://127.0.0.1:8080/[/code] 
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  服务器 多线程