创建web服务器

1 创建返回固定数据的web服务器:通过 localhost:8000/index.html 进行访问

import socket

if __name__ == '__main__':
    # socket.AF_INET :IPv4 地址   socket.SOCK_STREAM: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_prot = tcp_server_socket.accept()
        # 代码执行到此 说明链接成功
        # 接受客户端的请求消息
        recv_data = new_socket.recv(4096)
        print(recv_data)
        # 打开文件读取文件中的数据
        with open("index.html","r",encoding='utf-8') as file:
            # 读取文件
            file_data = file.read()
            # 设置响应行
            response_line = "HTTP/1.1 200 Ok\r\n"
            # 设置响应头
            response_Header = "Server:PWS/1.0\r\n"
            # 设置响应体
            response_body = file_data
            # 拼接 响应体
            response = response_line + response_Header + "\r\n" + response_body
            # 设置二级制数据
            response_data = response.encode('utf-8')
            # 给服务端响应数据
            new_socket.send(response_data)
            # 断开链接
            new_socket.close()

2 根据不同的请求 返回不同的数据

import socket

if __name__ == '__main__':

    # socket.AF_INET :IPv4 地址   socket.SOCK_STREAM: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_prot = tcp_server_socket.accept()
        # 接收客户端发送的消息 接收过来的是二进制消息 需要进行解码
        recv_data = new_socket.recv(4096)
        # 对二进制消息进行解码  接收的是客户端 请求报文的消息
        recv_content = recv_data.decode('utf-8')
        print(recv_content)
        # 对请求报文的消息 进行截取 获取URL地址栏的信息
        request_list = recv_content.split(' ',maxsplit=2) # 根据空格截取 只截取最前面的两个
        request_path = request_list[1] # /index.html
        # 读取文件  rb 模式兼容图片等
        with open('./'+request_path,'rb',) as file:
            file_data = file.read()
        # 设置响应行
        response_line = 'HTTP/1.1 200 OK\r\n'
        # 设置响应头
        response_header = "Server:PWS/1.0\r\n"
        # 响应体
        response_body = file_data
        # 进行拼接 转化为二进制
        response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
        # 给客户端响应消息
        new_socket.send(response)
        # 关闭链接
        new_socket.close()

3 处理发生错误的情况,比如访问的页面不存在返回404页面,比如 访问 /  返回index.html页面。

 

import socket

def main():
    # socket.AF_INET :IPv4 地址   socket.SOCK_STREAM: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_prot = tcp_server_socket.accept()
        # 接收客户端发送的消息 接收过来的是二进制消息 需要进行解码
        recv_data = new_socket.recv(4096)

        # 判断接收的消息是否为空  如果是空的话就关闭链接
        if len(recv_data) == 0:
            new_socket.close()
            return

            # 对二进制消息进行解码  接收的是客户端 请求报文的消息
        recv_content = recv_data.decode('utf-8')
        print(recv_content)
        # 对请求报文的消息 进行截取 获取URL地址栏的信息
        request_list = recv_content.split(' ', maxsplit=2)  # 根据空格截取 只截取最前面的两个
        request_path = request_list[1]  # /index.html

        # 判断请求是否是跟目录 如果是返回index.html
        if request_path == "/":
            request_path = '/index.html'

        # 判断读取的文件是否存在 如果不存在返回 404 页面
        try:
            # 读取文件  rb 模式兼容图片等
            with open('./' + request_path, 'rb', ) as file:
                file_data = file.read()
        except Exception as e:
            with open("error.html",'rb') as file:
                file_data = file.read()
                # 设置响应行
                response_line = 'HTTP/1.1 200 OK\r\n'
                # 设置响应头
                response_header = "Server:PWS/1.0\r\n"
                # 响应体
                response_body = file_data
                # 进行拼接 转化为二进制
                response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
                # 给客户端响应消息
                new_socket.send(response)
        else:
            # 设置响应行
            response_line = 'HTTP/1.1 200 OK\r\n'
            # 设置响应头
            response_header = "Server:PWS/1.0\r\n"
            # 响应体
            response_body = file_data
            # 进行拼接 转化为二进制
            response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
            # 给客户端响应消息
            new_socket.send(response)
        finally:
            # 关闭链接
            new_socket.close()

if __name__ == '__main__':
    main()

4  创建多线程web服务器 

import socket
import threading

def handle_client_request(new_socket):
    recv_data = new_socket.recv(4096)

    if len(recv_data) == 0:
        new_socket.close()
        return

    # 对二进制消息进行解码  接收的是客户端 请求报文的消息
    recv_content = recv_data.decode('utf-8')
    print(recv_content)

    # 对请求报文的消息 进行截取 获取URL地址栏的信息
    request_list = recv_content.split(' ', maxsplit=2)  # 根据空格截取 只截取最前面的两个
    request_path = request_list[1]  # /index.html

    # 判断请求是否是跟目录 如果是返回index.html
    if request_path == "/":
        request_path = '/index.html'

    # 判断读取的文件是否存在 如果不存在返回 404 页面
    try:
        # 读取文件  rb 模式兼容图片等
        with open('./' + request_path, 'rb', ) as file:
            file_data = file.read()
    except Exception as e:
        with open("error.html", 'rb') as file:
            file_data = file.read()
            # 设置响应行
            response_line = 'HTTP/1.1 200 OK\r\n'
            # 设置响应头
            response_header = "Server:PWS/1.0\r\n"
            # 响应体
            response_body = file_data
            # 进行拼接 转化为二进制
            response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
            # 给客户端响应消息
            new_socket.send(response)
    else:
        # 设置响应行
        response_line = 'HTTP/1.1 200 OK\r\n'
        # 设置响应头
        response_header = "Server:PWS/1.0\r\n"
        # 响应体
        response_body = file_data
        # 进行拼接 转化为二进制
        response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
        # 给客户端响应消息
        new_socket.send(response)
    finally:
        # 关闭链接
        new_socket.close()


def main():
    # socket.AF_INET :IPv4 地址   socket.SOCK_STREAM: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_prot = tcp_server_socket.accept()
        # 创建多线程
        sub_thread = threading.Thread(target=handle_client_request,args=(new_socket,))
        # 设置成为守护主线
        sub_thread.setDaemon(True)
        # 启动子线程
        sub_thread.start()

if __name__ == '__main__':
    main()

5 使用类创建web服务器,创建一个处理数据的函数, 创建一个类(初始化websock,启动websocket)

import socket
import threading

def handle_client_request(new_socket):
    recv_data = new_socket.recv(4096)

    if len(recv_data) == 0:
        new_socket.close()
        return

    # 对二进制消息进行解码  接收的是客户端 请求报文的消息
    recv_content = recv_data.decode('utf-8')
    print(recv_content)

    # 对请求报文的消息 进行截取 获取URL地址栏的信息
    request_list = recv_content.split(' ', maxsplit=2)  # 根据空格截取 只截取最前面的两个
    request_path = request_list[1]  # /index.html

    # 判断请求是否是跟目录 如果是返回index.html
    if request_path == "/":
        request_path = '/index.html'

    # 判断读取的文件是否存在 如果不存在返回 404 页面
    try:
        # 读取文件  rb 模式兼容图片等
        with open('./' + request_path, 'rb', ) as file:
            file_data = file.read()
    except Exception as e:
        with open("error.html", 'rb') as file:
            file_data = file.read()
            # 设置响应行
            response_line = 'HTTP/1.1 200 OK\r\n'
            # 设置响应头
            response_header = "Server:PWS/1.0\r\n"
            # 响应体
            response_body = file_data
            # 进行拼接 转化为二进制
            response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
            # 给客户端响应消息
            new_socket.send(response)
    else:
        # 设置响应行
        response_line = 'HTTP/1.1 200 OK\r\n'
        # 设置响应头
        response_header = "Server:PWS/1.0\r\n"
        # 响应体
        response_body = file_data
        # 进行拼接 转化为二进制
        response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
        # 给客户端响应消息
        new_socket.send(response)
    finally:
        # 关闭链接
        new_socket.close()


class HttpWebServer():
    def __init__(self):
        # ipv4 地址  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

    # 启动服务器的方法
    def start(self):
        while True:
            new_socket,ip_port = self.tcp_server_socket.accept()
            sub_thread = threading.Thread(target=handle_client_request,args=(new_socket,))
            sub_thread.setDaemon(True)
            sub_thread.start()


def main():
    web_server = HttpWebServer()
    web_server.start()

if __name__ == '__main__':
    main()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值