python-web服务器1-创建简单的web服务端(多进程、线程、协程实现)

​前言​:此为python学习笔记,如错误或争议敬请发送到邮箱 zytwell321@163.com ,万分感谢​!

1.单线程服务

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re


def service_client(new_socket):
    """ 为客户端提供返回数据 """
    # 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
    # ...
    request_data = new_socket.recv(1024).decode("utf-8")
    print(request_data)

    # 将请求结果分割成列表
    request_lines = request_data.splitlines()
    # print(">" * 20)
    # print(request_lines)

    # GET /html/index.html HTTP/1.1
    # GET / HTTP/1.1
    # 请求类型:GET POST DELETE ...
    file_name = ""
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)                    # 提取请求路径
        print("*" * 30, file_name)
        if file_name == "/":
            file_name = "/index.html"

    # 2.返回http格式信息给客户端浏览器
    try:
        f = open("./html" + file_name, "rb")      # 打开url访问路径文件
    except:
        response = "HTTP/1.1 404\r\n"
        response += "\r\n"
        response += "<h1>404</h1>\r\nFILE NOT FOUND"
        new_socket.send(response.encode("utf-8"))
    else:
        html_content = f.read()
        f.close()
        # 2.1 组装返回给浏览器的数据-- header
        print(" " * 50)
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        # 2.2 组装返回给浏览器的数据-- body
        # response += "<h1>hello world</h1>\r\n"     # 调试:返回固定结果
        # f = open("./html/test.html", "rb")         # 调试:返回固定页面

        # 返回给浏览器报文头 respone header
        new_socket.send(response.encode("utf-8"))
        # 返回给浏览器报文体 reponse body
        new_socket.send(html_content)

    # 3.关闭套接字
    new_socket.close()


def main():
    """ tcp-socket 流程控制 """
    # 1.创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
    tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 2.绑定
    tcp_socket_server.bind(("",8080))
    # 3.创建套接字监听
    tcp_socket_server.listen(128)

    # 4.服务完毕,关闭套接字
    while True:
        # 4.等待新客户端连接
        new_socket, client_addr = tcp_socket_server.accept()
        # 5.为客户端提供服务
        service_client(new_socket)

    tcp_socket_server.close()


if __name__ == "__main__":
    main()

浏览器显示内容:

服务端接收到请求:

GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9


****************************** /

遗留问题:

浏览器访问连接一段时间后,断开服务端。服务端响应提示如下:

Traceback (most recent call last):
  File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 88, in <module>
    main()
  File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 82, in main
    service_client(new_socket)
  File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 31, in service_client
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
IndexError: list index out of range
 

2.多进程服务

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re
import multiprocessing


def service_client(new_socket):
    """ 为客户端提供返回数据 """
    # 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
    # ...
    request_data = new_socket.recv(1024).decode("utf-8")
    print(request_data)

    # 将请求结果分割成列表
    request_lines = request_data.splitlines()
    # print(">" * 20)
    # print(request_lines)

    # GET /html/index.html HTTP/1.1
    # GET / HTTP/1.1
    # 请求类型:GET POST DELETE ...
    file_name = ""
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)                    # 提取请求路径
        print("*" * 30, file_name)
        if file_name == "/":
            file_name = "/index.html"

    # 2.返回http格式信息给客户端浏览器
    try:
        f = open("./html" + file_name, "rb")      # 打开url访问路径文件
    except:
        response = "HTTP/1.1 404\r\n"
        response += "\r\n"
        response += "<h1>404</h1>\r\nFILE NOT FOUND"
        new_socket.send(response.encode("utf-8"))
    else:
        html_content = f.read()
        f.close()
        # 2.1 组装返回给浏览器的数据-- header
        print(" " * 50)
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        # 2.2 组装返回给浏览器的数据-- body
        # response += "<h1>hello world</h1>\r\n"     # 调试:返回固定结果
        # f = open("./html/test.html", "rb")         # 调试:返回固定页面

        # 返回给浏览器报文头 respone header
        new_socket.send(response.encode("utf-8"))
        # 返回给浏览器报文体 reponse body
        new_socket.send(html_content)

    # 3.关闭套接字
    new_socket.close()


def main():
    """ tcp-socket 流程控制 """
    # 1.创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
    tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 2.绑定
    tcp_socket_server.bind(("",8080))
    # 3.创建套接字监听
    tcp_socket_server.listen(128)

    # 4.服务完毕,关闭套接字
    while True:
        # 4.等待新客户端连接
        new_socket, client_addr = tcp_socket_server.accept()
        # 5.为客户端提供服务
        # service_client(new_socket)
        p = multiprocessing.Process(target=service_client, args=(new_socket,))
        p.start()
        new_socket.close()

    tcp_socket_server.close()


if __name__ == "__main__":
    main()

3.多线程服务

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re
import threading


def service_client(new_socket):
    """ 为客户端提供返回数据 """
    # 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
    # ...
    request_data = new_socket.recv(1024).decode("utf-8")
    print(request_data)

    # 将请求结果分割成列表
    request_lines = request_data.splitlines()
    # print(">" * 20)
    # print(request_lines)

    # GET /html/index.html HTTP/1.1
    # GET / HTTP/1.1
    # 请求类型:GET POST DELETE ...
    file_name = ""
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)                    # 提取请求路径
        print("*" * 30, file_name)
        if file_name == "/":
            file_name = "/index.html"

    # 2.返回http格式信息给客户端浏览器
    try:
        f = open("./html" + file_name, "rb")      # 打开url访问路径文件
    except:
        response = "HTTP/1.1 404\r\n"
        response += "\r\n"
        response += "<h1>404</h1>\r\nFILE NOT FOUND"
        new_socket.send(response.encode("utf-8"))
    else:
        html_content = f.read()
        f.close()
        # 2.1 组装返回给浏览器的数据-- header
        print(" " * 50)
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        # 2.2 组装返回给浏览器的数据-- body
        # response += "<h1>hello world</h1>\r\n"     # 调试:返回固定结果
        # f = open("./html/test.html", "rb")         # 调试:返回固定页面

        # 返回给浏览器报文头 respone header
        new_socket.send(response.encode("utf-8"))
        # 返回给浏览器报文体 reponse body
        new_socket.send(html_content)

    # 3.关闭套接字
    new_socket.close()


def main():
    """ tcp-socket 流程控制 """
    # 1.创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
    tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 2.绑定
    tcp_socket_server.bind(("",8080))
    # 3.创建套接字监听
    tcp_socket_server.listen(128)

    # 4.服务完毕,关闭套接字
    while True:
        # 4.等待新客户端连接
        new_socket, client_addr = tcp_socket_server.accept()
        # 5.为客户端提供服务
        # service_client(new_socket)
        t = threading.Thread(target=service_client, args=(new_socket,))
        t.start()

    tcp_socket_server.close()


if __name__ == "__main__":
    main()

4.协程实现http服务

"""
使用协程完成http服务器
"""

import socket
import re
import gevent
from gevent import monkey

monkey.patch_all()

def service_client(new_socket):
    """ 为客户端提供返回数据 """
    # 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
    # ...
    request_data = new_socket.recv(1024).decode("utf-8")
    print(request_data)

    # 将请求结果分割成列表
    request_lines = request_data.splitlines()
    # print(">" * 20)
    # print(request_lines)

    # GET /html/index.html HTTP/1.1
    # GET / HTTP/1.1
    # 请求类型:GET POST DELETE ...
    file_name = ""
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)                    # 提取请求路径
        print("*" * 30, file_name)
        if file_name == "/":
            file_name = "/index.html"

    # 2.返回http格式信息给客户端浏览器
    try:
        f = open("./html" + file_name, "rb")      # 打开url访问路径文件
    except:
        response = "HTTP/1.1 404\r\n"
        response += "\r\n"
        response += "<h1>404</h1>\r\nFILE NOT FOUND"
        new_socket.send(response.encode("utf-8"))
    else:
        html_content = f.read()
        f.close()
        # 2.1 组装返回给浏览器的数据-- header
        print(" " * 50)
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        # 2.2 组装返回给浏览器的数据-- body
        # response += "<h1>hello world</h1>\r\n"     # 调试:返回固定结果
        # f = open("./html/test.html", "rb")         # 调试:返回固定页面

        # 返回给浏览器报文头 respone header
        new_socket.send(response.encode("utf-8"))
        # 返回给浏览器报文体 reponse body
        new_socket.send(html_content)

    # 3.关闭套接字
    new_socket.close()


def main():
    """ tcp-socket 流程控制 """
    # 1.创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
    tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 2.绑定
    tcp_socket_server.bind(("",8080))
    # 3.创建套接字监听
    tcp_socket_server.listen(128)

    # 4.服务完毕,关闭套接字
    while True:
        # 4.等待新客户端连接
        new_socket, client_addr = tcp_socket_server.accept()
        # 5.为客户端提供服务
        gevent.spawn(service_client, new_socket)

    #tcp_socket_server.close()


if __name__ == "__main__":
    main()
 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值