web 服务器

楚硕
2023-12-01
执行mian ()函数


def  main 函数():

	创建套接字

 	重启占用的端口

	绑定端口号

	设置监听



	循环 :

		等待客户端的连接

		创建进程 

		运行进程

		关闭客户端连接

	关闭套接字





def  进程函数():  ------为客户端返回数据------

	接收客户端发送来的内容 (即http 请求 )    recv .decode ('utf-8')

	编码后的内容直接用  正则 取出网页名       search("/\s*" ,  或者 match( r"[ ^/] +(/[ ^  ] *)"  ,

	判断客户端请求的 文件 是否存在

  		存在则 打印 正则取出网页 .group() 

 		判断设置默认网页

	try:  

 		拼接路径,在当前的 目录中寻找对应的文件读取

 	except:

 		如果没找到拼接错误的信息

  		响应行 =

		响应头 =

 		响应体 =   "错误...."

	else:

		没有错误则返回对应的文件

		响应行 =

		响应头 =

 		响应体 =   

		返回给客户端

 	 	 



 	




import socket,re,os

a = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
b =a.bind(("",8989))
a.listen(128)

while True:
    aa ,bb =a.accept()
    jieshou = aa.recv(1024)
    # print("接收:",jieshou)
    bianma = jieshou.decode("utf-8")
    # print("编码:",bianma)
    zhengze =re.search("/\S*",bianma)
    if zhengze:
        jieguo = zhengze.group()
        print("jieguo.............",jieguo)
        if jieguo == "/":
            jieguo = "/index.html"


        if os.path.exists("static"+jieguo):
            with open("static" + jieguo, "rb") as file:
                # 读取文件中的全部数据
                file_data = file.read()



                # 响应行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 响应头
                response_header = "Server: PWS/1.1\r\nother:ok\r\nContent-Type: text/html;charset=utf-8\r\n"
                # 响应体
                response_body = file_data
                # 组装http响应报文数据
                response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body

                # 发送http 响应报文数据给客户端
                aa.send(response_data)
                # 关闭套接字


        else:
            with open("static"+"/"+"cuowu.html" ,"rb" )as cuowuxx_html:

                cuwu_neirong = cuowuxx_html.read()
                aaaa= cuwu_neirong.decode("utf-8")

                # 响应行
                response_line = "HTTP/1.1 404 Not Found\r\n"
                # 响应头, 提示: 响应头信息程序员也可以根据自己的需要自定义一个响应头信息
                # Content-Type: text/html;charset=utf-8: 服务器告诉浏览器数据的类型及编码格式
                response_header = "Server: PWS/1.1\r\nother:ok\r\nContent-Type: text/html;charset=utf-8\r\n"
                # 响应体
                response_body = aaaa
                # 组装http响应报文数据
                response_data = (response_line + response_header + "\r\n" + response_body).encode("utf-8")

                # 发送http 响应报文数据给客户端
                aa.send(response_data)

    aa.close()







代码实现:

import socket
import re
import multiprocessing


def service_client(new_socket):
    """为客户端返回数据"""

    # 1. 接收浏览器发送过来的请求 ,即http请求相关信息
    # GET / HTTP/1.1
    # .....
    request = new_socket.recv(1024).decode("utf-8")
    #将请求头信息进行按行分解存到列表中
    request_lines = request.splitlines()
    # GET /index.html HTTP/1.1
    file_name = ""
    #正则:  [^/]+ 不以/开头的至少一个字符 匹配到/之前
    #      (/[^ ]*) 以分组来匹配第一个字符是/,然后不以空格开始的0到多个字符,也就是空格之前
    #      最后通过匹配可以拿到 请求的路径名  比如:index.html
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    #如果匹配结果 不为none,说明请求地址正确
    if ret:
        #利用分组得到请求地址的文件名,正则的分组从索引1开始
        file_name = ret.group(1)
        print('FileName:  ' + file_name)
        #如果请求地址为 / 将文件名设置为index.html,也就是默认访问首页
        if file_name == "/":
            file_name = "/index.html"

    # 2. 返回http格式的数据,给浏览器
    try:
        #拼接路径,在当前的html目录下找访问的路径对应的文件进行读取
        f = open("./html" + file_name, "rb")
    except:
        #如果没找到,拼接响应信息并返回信息
        response = "HTTP/1.1 404 NOT FOUND\r\n"
        response += "\r\n"
        response += "------file not found-----"
        new_socket.send(response.encode("utf-8"))
    else:
        #如果找到对应文件就读取并返回内容
        html_content = f.read()
        f.close()
        # 2.1 准备发送给浏览器的数据---header
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        #如果想在响应体中直接发送文件内的信息,那么在上面读取文件时就不能用rb模式,只能使用r模式,所以下面将响应头和响应体分开发送
        #response += html_content
        # 2.2 准备发送给浏览器的数据
        # 将response header发送给浏览器
        new_socket.send(response.encode("utf-8"))
        # 将response body发送给浏览器
        new_socket.send(html_content)

    # 关闭套接
    new_socket.close()

def main():
    """用来完成整体的控制"""
    # 1. 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #用来重新启用占用的端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # 2. 绑定IP和端口号
    tcp_server_socket.bind(("", 7890))

    # 3. 设置套接字监听连接数(最大连接数)
    tcp_server_socket.listen(128)

    while True:
        # 4. 等待新客户端的链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 5. 为连接上来的客户端去创建一个新的进程去运行
        p = multiprocessing.Process(target=service_client, args=(new_socket,))
        p.start()
        #因为新进程在创建过程中会完全复制父进程的运行环境,所以父线程中关闭的只是自己环境中的套接字对象
        #而新进程中因为被复制的环境中是独立存在的,所以不会受到影响
        new_socket.close()

    # 关闭监听套接字
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

 类似资料: