python实现外部静态服务器,浏览器通过HTTP与之通信2

        因为网络间通信是基于TCP协议传输数据的,而服务器与浏览器之间通信是基于HTTP协议的,那么下面基于python实现一个tcp服务器,浏览器可以基于http协议进行发送请求和解析。浏览器展示返回的一个标准的HTML网页,此外实现服务器解析客户端多次请求并且返回请求结果。即:客户端根据HTML里面的各种链接,再发送HTTP请求给服务器,拿到相应的图片、视频、Flash、JavaScript脚本、CSS等各种资源,最终显示出一个完整的页面。

1.代码实现web服务器,实现解析用户请求并且返回对应结果

#coding=utf-8
import socket
import re

def handle_client(client_socket):
    "为一个客户端进行服务"
    recv_data = client_socket.recv(1024).decode('gbk', errors="ignore") #报错忽略
    '''
    注意尽管客户端可以根据返回的HTML里的链接发送二次请求,但是要想正确返回请求内容,需要服务器能够解析
    这些请求内容,找到这些内容读取后send给客户端。所以下面要做的就是解析客户端的请求如下格式:
    b'GET /images/qt-logo.png HTTP/1.1\r\nHost: 127.0.0.1:7890\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:7890/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
    '''
    request_header_lines = recv_data.splitlines() #1.将服务器接收的数据按HTTP格式进行切分,模式分割符就是\r\n
    for line in request_header_lines:   #打印是为了测试使用
        print(line)

    http_request_line = request_header_lines[0]  #2.获取请求数据的第一行,比如:GET /images/qt-logo.png HTTP/1.1
    get_file_name = re.match("[^/]+(/[^ ]*)", http_request_line).group(1)  #3.获取客户端请求的文件名images/qt-logo.png
    print("file name is ===>%s" % get_file_name)  # for test

    # 如果没有指定访问哪个页面。例如index.html
    # GET / HTTP/1.1
    if get_file_name == "/":
        get_file_name = DOCUMENTS_ROOT + "/index.html"
    else:
        get_file_name = DOCUMENTS_ROOT + get_file_name

    print("file name is ===2>%s" % get_file_name) #for test

    try:
        f = open(get_file_name, "rb")
    except IOError: #如果没有该文件,则返回404 not found
        # 404表示没有这个页面
        response_headers = "HTTP/1.1 404 not found\r\n"
        response_headers += "\r\n"
        response_body = "====sorry ,file not found===="
    else:  #注意这里else的使用,找到了该文件返回200 OK
        response_headers = "HTTP/1.1 200 OK\r\n"
        response_headers += "\r\n"
        response_body = f.read() #读取用户请求的文件,注意这里如果文件很大,可以循环读取
        f.close()

    finally:# 在这里将读取的文件发送给客户端。
        # 因为头信息在组织的时候,是按照字符串组织的,不能与以二进制打开文件读取的数据合并,因此分开发送
        # 先发送response的头信息
        client_socket.send(response_headers.encode('gbk')) #注意如果在linux上测试的话,改成utf-8
        # 再发送body
        client_socket.send(response_body)
        client_socket.close()

def main():
    "作为程序的主控制入口"
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置当服务器先close 即服务器端4次挥手之后资源能够立即释放,这样就保证了,下次运行程序时 可以立即绑定7788端口
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(("", 7788))
    server_socket.listen(128)
    while True:
        client_socket, clien_cAddr = server_socket.accept()
        handle_client(client_socket)


#这里配置服务器
DOCUMENTS_ROOT = "./html"  #因为文件都放在当前路径下的html文件夹里,所以这里定义一个固定路径,存放的是提前写好的网页文件。

if __name__ == "__main__":
    main()

2.测试展示与分析

       启动上面程序,打开web浏览器,访问该服务器。注意,之前我们服务器是固定返回一个页面给浏览器,不去对请求的数据进行解析处理,所以192.168.1.1:7788后面跟任何字符串都行,都不会报错,现在则不行,服务器会对浏览器的请求进行解析,如下因为找不到/aaaa/bbbb/ccc而报错,404 NOT FOUND

2.1错误访问地址

  2.2.正常向服务器发送请求

     所以这个时候我们就需要按服务器上的正常部署是文件去访问了.比如我们在服务器上配置默认的路径就是index.html,所以我们直接用浏览器访问http://192.168.1.1:7788/index.html 或者http://192.168.1.1:7788结果都是一样,如下,注意下面网页的图片已经加载正常了。实现了客户端根据HTML里面的各种链接,再发送HTTP请求给服务器,拿到相应的图片、视频、Flash、JavaScript脚本、CSS等各种资源,最终显示出一个完整的页面

2.3服务器内部打印的浏览器请求与解析后的结果如下: 

  可以看出虽然请求了一次,但是浏览器因为网页内嵌的url,随后发送了多次请求,并且都得到了正确响应。

GET / HTTP/1.1
Host: 192.168.1.1:7788
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/75.0.3770.80 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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

file name is ===>/
file name is ===2>./html/index.html
GET /classic.css HTTP/1.1
Host: 192.168.1.1:7788
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36
Accept: text/css,*/*;q=0.1
Referer: http://192.168.1.1:7788/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

file name is ===>/classic.css
file name is ===2>./html/classic.css
GET /images/qt-logo.png HTTP/1.1
Host: 192.168.1.1:7788
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://192.168.1.1:7788/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

file name is ===>/images/qt-logo.png
file name is ===2>./html/images/qt-logo.png
GET /images/trolltech-logo.png HTTP/1.1
Host: 192.168.1.1:7788
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://192.168.1.1:7788/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

file name is ===>/images/trolltech-logo.png
file name is ===2>./html/images/trolltech-logo.png
发布了248 篇原创文章 · 获赞 1600 · 访问量 267万+

猜你喜欢

转载自blog.csdn.net/qq_26442553/article/details/95317310