一、最简单的WEB页面访问过程

   互联网应用都要经过通过OSI层封装解封装来达到远程访问效果。python中有写好的socket模块帮助开发人员实现这个功能,因此开发人员只要把注意力放在客户端和服务端。对于WEB来说,客户端就是浏览器,服务端则是提供页面的程序所在的机器。客户端已有成熟的各种浏览器,那么做出符合各种需求的页面就比较关键。

  (1)首先模拟服务器程序

   一个简单套import socket #导入socket模块

sock = socket.socket()#实例化socket对象
sock.bind(('127.0.0.1',9000)) #绑定ip地址和端口号
sock.listen(5)  #设置监听的客户端数量
while True:
    conn, ddr = sock.accept()#conn是客户端和服务端建立的链接,ddr是客户端地址加端口号
    print(conn)#<socket.socket fd=440, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, 
  laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 57951)> print(ddr)#('127.0.0.1', 57951) data = conn.recv(1024) #接受客户端访问的数据 conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello web') # 向客户端发送数据,因为使用的浏览器,所以要加个HTTP标准格式,不然浏览器无法解析

 

  使用浏览器访问:

  

  以上就是最基础的WEB访问过程,服务器返回的是一个二进制字符串数据,浏览器解析后变为正常的字符串显示在页面,而实际中则是要复杂得多。

  (2)使用html显示页面

    如果想构建复杂页面,光靠一行行send二进制信息给浏览器解析是很不方便的。一方面不便于编写,另一方面也不适合维护。所以通过写html文件,然后利用open函数读取htlm,再发送给浏览器解析则方便许多。

    代码修改:

    

import socket #导入socket模块
sock = socket.socket()#实例化socket对象
sock.bind(('127.0.0.1',9000)) #绑定ip地址和端口号
sock.listen(5)  #设置监听的客户端数量
while True:
    conn, ddr = sock.accept()#conn是客户端和服务端建立的链接,ddr是客户端地址加端口号
    data = conn.recv(1024)  # 接受客户端访问的数据
    with open('index.html','r') as f:
        data_html = f.read()
    conn.send(("HTTP/1.1 200 OK\r\n\r\n%s"%data_html).encode('utf-8')) # 向客户端发送html文件的二进制信息

 

  这样只要单独编写html文件,然后通过读取文件方式再发送给浏览器,就可以方便的实现更复杂的页面效果。

 (3)HTTP的请求和响应

  我们先看看上述最简单的WEB访问程序如何工作的。

  通过浏览器开发者选项下的Network可以看到:

  

 

  浏览器通过向服务器发送GET请求来获得响应,实际是得到了服务器返回的html代码然后解析成对应的页面。下面简单介绍HTTP请求过程。

  HTTP请求报文由三部分组成:请求行,请求头和请求正文

  b'GET / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0;   WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'

  请求行:指的是“GET / HTTP/1.1”,这种指明请求类型(有get或post)、URL路径、HTTP协议和版本号的代码行。

  请求头:指的是由\r\n分割的代码内容。里面包含了Host、Connection等信息。

  请求正文:指的是由\r\n\r\n分割的代码内容。

  HTTP响应报文也有三部分构成:响应行,响应头和实体内容  

  "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n%s"%data_html

  响应行:指的是
\r\n前面的HTTP协议及版本号和状态码。其中状态码有1XX、2XX、3XX、4XX、5XX等,通常1XX表示在正在处理接受的请求,2XX表示请求处理完毕、3XX表示重定向,
指的是服务器返回给浏览器需要重新访问的页面地址,相当于两次HTTP请求过程。4XX通常表示客户端请求错误指的是URL不正确等,5XX表示的是服务器处理请求出错,为服务端程序错误。
  响应头:指的是\r\n和\r\n\r\n中间的内容,在浏览器中可以看到:

  

  实体内容:指的是r\n\r\n之后的代码,也是浏览器要解析的html代码,通过它浏览器才能解析、渲染来向用户提供页面。