HTTP协议简介
- 使用谷歌/火狐浏览器分析
在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议是HTTP,所以:
-
HTML是一种用来定义网页的文本,会HTML,就可以编写网页;
-
HTTP是在网络上传输HTML的协议,用于浏览器和服务器的通信。
Chrome浏览器提供了一套完整地调试工具,非常适合Web开发。
安装好Chrome浏览器后,打开Chrome,在菜单中选择“视图”,“开发者”,“开发者工具”,就可以显示开发者工具:
说明
Elements显示网页的结构
Network显示浏览器和服务器的通信
我们点Network,确保第一个小红灯亮着,Chrome就会记录所有浏览器和服务器之间的通信:
说明
Elements显示网页的结构
Network显示浏览器和服务器的通信
我们点Network,确保第一个小红灯亮着,Chrome就会记录所有浏览器和服务器之间的通信:
2. http协议的分析
当我们在地址栏输入www.sina.com时,浏览器将显示新浪的首页。在这个过程中,浏览器都干了哪些事情呢?通过Network的记录,我们就可以知道。在Network中,找到www.sina.com那条记录,点击,右侧将显示Request Headers,点击右侧的view source,我们就可以看到浏览器发给新浪服务器的请求:
2.1 浏览器请求
说明
最主要的头两行分析如下,第一行:
GET / HTTP/1.1
GET表示一个读取请求,将从服务器获得网页数据,/表示URL的路径,URL总是以/开头,/就表示首页,最后的HTTP/1.1指示采用的HTTP协议版本是1.1。目前HTTP协议的版本就是1.1,但是大部分服务器也支持1.0版本,主要区别在于1.1版本允许多个HTTP请求复用一个TCP连接,以加快传输速度。
从第二行开始,每一行都类似于Xxx: abcdefg:``
Host: www.sina.com
总结
HTTP请求
跟踪了新浪的首页,我们来总结一下HTTP请求的流程:
步骤1:浏览器首先向服务器发送HTTP请求,请求包括:
方法:GET还是POST,GET仅请求资源,POST会附带用户数据;
路径:/full/url/path;
域名:由Host头指定:Host: www.sina.com
以及其他相关的Header;
如果是POST,那么请求还包括一个Body,包含用户数据
步骤2:服务器向浏览器返回HTTP响应,响应包括:
响应代码:200表示成功,3xx表示重定向,4xx表示客户端发送的请求有错误,5xx表示服务器端处理时发生了错误;
响应类型:由Content-Type指定;
以及其他相关的Header;
通常服务器的HTTP响应会携带内容,也就是有一个Body,包含响应的内容,网页的HTML源码就在Body中。
步骤3:如果浏览器还需要继续向服务器请求其他资源,比如图片,就再次发出HTTP请求,重复步骤1、2。
Web采用的HTTP协议采用了非常简单的请求-响应模式,从而大大简化了开发。当我们编写一个页面时,我们只需要在HTTP请求中把HTML发送出去,不需要考虑如何附带图片、视频等,浏览器如果需要请求图片和视频,它会发送另一个HTTP请求,因此,一个HTTP请求只处理一个资源(此时就可以理解为TCP协议中的短连接,每个链接只获取一个资源,如需要多个就需要建立多个链接)
HTTP协议同时具备极强的扩展性,虽然浏览器请求的是http://www.sina.com的首页,但是新浪在HTML中可以链入其他服务器的资源,比如,从而将请求压力分散到各个服务器上,并且,一个站点可以链接到其他站点,无数个站点互相链接起来,就形成了World Wide Web,简称WWW。
Web静态服务器-显示需要的页面
#coding=utf-8
import socket
import re
def client(new_sok):
"""为这个客户端返回数据"""
# 接受浏览器发送过来的请求,即http请求
request = new_sok.recv(1024),decode("utf-8)
# 切割request列表
request_lines = requse.splitlines()
# 返回http格式的数据给浏览器
# 准备发给浏览器的数据---header
file_name = ""
ret = re.match(r"[^/]+(/[^ ])*", request_lines[0])
# 如果正则表达式判断成立
if ret:
flie_name = ret.group(1)
# 如果没有指定访问哪个页面
if file_name == "/":
flie_name = "/index.html"
try: # 打开文件
f = open("./html" + file_name, "rb")
except: # 如果没有这个文件或者打开失败
# 返回给浏览器response
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "\r\n"
response += "404 NOT FOUND"
new_sok.send(response.encode("utf-8"))
else: # 如果打开成功返回给浏览器这个文件内容
html_content = f.read()
f.close()
# 准备发给浏览器的数据---header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 准备发给浏览器的数据---body
new_sok.send(response.encode("utf-8"))
new_sok.send(html_content)
# 关闭套接字
new_sok.close()
def main():
# 创建套接字
sok = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sok.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定本地信息
sok.bind("",7890)
# 变为监听套接字
sok.listen(128)
while True:
# 等待新客户端链接
new_sok, ulr_ip = sok.accept()
client(new_sok)
# 关闭套接字
sok.close()
if __name__ == "__main__":
main()
说明:
文件必须在当前目录下或者把代码路径改了