欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

web 服务器

程序员文章站 2022-05-08 23:49:38
...
执行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()