04-返回指定页面内容

目标

  • 能够实现 根据浏览器不同请求 返回对应网页资源的Web服务器

image-20180727205110542

1. 功能分析

1、Web服务器能够绑定固定端口

2、Web服务器端能够接收浏览器请求

3、Web服务器遵守HTTP协议,根据请求返回指定的html 内容给浏览器

4、当浏览器关闭后,Web服务器能够显示断开连接

5、Web服务器短时间内重启,不会提示 address already in use 错误

2. 实现思路

1、导入socket模块

2、创建tcp套接字

3、设置地址重用

4、绑定端口

5、设置监听,最大允许客户端连接数128(套接字有主动变为被动)

6、等待客户端连接(能够接受多个客户端连接)

7、定义函数,实现客户端信息接收和响应

​ 8、接收浏览器请求,并判断请求是否为空

​ 9、拼接响应报文

​ 10、定义变量保存响应报文内容

​ 11、获取浏览器发送的请求头信息,分析并得到请求html文件路径

​ 12、根据路径信息,打开指定的html文件,并返回内容给客户端浏览器

​ 13、发送响应报文给客户端浏览器(注意转码问题)

​ 14、关闭此次连接的套接字

3. 代码实现

import socket
import re


def request_handler(new_client_socket):
    """ 响应客户端请求的核心函数 """
    request_data = new_client_socket.recv(1024)
    # 判断客户端是否已经断开链接
    if not request_data:

        print("客户端已经断开连接!")
        # 关闭当前连接
        new_client_socket.close()

        # 退出,代码不再向后执行
        return

    # 目的:得到 客户端 请求行
    # 对客户端请求的数据进行分析
    request_data_str = request_data.decode()

    # 根据”\r\n“ 分割请求头,得到存储每行请求数据的列表
    request_list = request_data_str.split("\r\n")

    # print(request_list)
    # 使用正则 取出 请求头中的 路径部分
    ret = re.search(r"\s(.*)\s", request_list[0])
    if not ret:
        print("用户请求报文格式错误!")
        new_client_socket.close()
        return

    # 得到路径
    path_info = ret.group(1)
    print("接收到用户请求:", path_info)

    response_header = "Server:Python-Web1.0\r\n"
    response_blank = "\r\n"

    try:
        # 读取指定路径文件,并且返回
        with open("static"+path_info, "rb") as file:
            # 读取文件的二进制数据
            response_content = file.read()

    except Exception as e:
        # 开始拼接响应数据
        response_line = "HTTP/1.1 404 Not Found\r\n"
        response_content = "Error !!! %s" % str(e)
        response_content = response_content.encode()
    else:
        # 开始拼接响应数据
        response_line = "HTTP/1.1 200 OK\r\n"

    # 拼接响应头
    response_data = (response_line + response_header + response_blank).encode() + response_content

    # 发送数据
    new_client_socket.send(response_data)

    # 关闭socket
    new_client_socket.close()


def main():

    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置地址重用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 绑定IP 和端口
    tcp_server_socket.bind(("", 8080))

    # 设置套接字为被动套接字,主要接收客户端链接
    tcp_server_socket.listen(128)

    while True:
        # 接受客户端链接
        new_client_socket, ip_port = tcp_server_socket.accept()

        print("[新客户端上线]", ip_port)

        # 相应客户端请求,发送数据给客户端
        request_handler(new_client_socket)


if __name__ == '__main__':

    main()
运行结果:

web_v4-1324522

4. 默认首页判断

   # 设置默认请求页面为 index.html
   if path_info == "/":
        path_info = "/index.html"

image-20180712000020235

运行结果:

web_v4_2