分享

笔记整理:用socket实现Web开发框架流程

 丰收书屋 2022-10-22 发布于北京

笔记整理:用socket实现Web开发框架流程

基础概念

socket: socket是一种通信机制,通过绑定IP地址和端口产生一个通信链,实现计算机之间的通信。网络中不同的计算机之间进行通信必须经过IP地址和端口,为了降低网络通信开发的复杂度,人们在TCP/IP4层结构中的应用层与传输层之间加了一层,这个层就是socket层。它把复杂的TCP/IP进行了封装,并提供了一组服务的接口。

Web服务: Web服务本质上是由socket服务端向socket客户端提供HTTP响应,而浏览器就是一个socket客户端。网络中的服务器主机会提供一种或多种服务,每一种服务打开一个socket,并绑定到一个端口上,也就是说不同的端口对应着不同的服务,客户端向那个端口发送请求,就会得到相应的服务。当用户在浏览器地址栏输入网址(URL)并确定时,这个动作称为发送Web请求,网络中会有一台与网址相对应的服务器按用户的请求做出相应,把请求资源发送给用户。这台接收Web请求并作出相应的服务器成为Web服务器,它把用户请求的资源以HTML文件的形式传递给用户的浏览器。

Web应用的本质: Web应用主要做的事情就是发送HTML文件到浏览器,其核心功能则通过socket服务完成。因此Web服务器本质上是一个socket服务端,浏览器本质上是一个socket客户端。

Web开发框架的运行方式

根据上文对socket服务的描述我们可以简单地将Web通信流程理解成三个步骤:

浏览器向服务器发出请求 ——> 服务器接收到请求信息并根据一定的逻辑确定需要反馈的内容 ——> 服务器将反馈的内容传递给浏览器

建立socket服务

想要用socket实现以上流程,我们第一步应该做的就是在浏览器(客户端)与服务器之间建立联系,否则双方不能接收对方的请求或者反馈就一切都没有意义:

import socket

sk = socket.socket()   #建立socket服务(本文第一段第而三行)
sk.bind(('127.0.0.1',8000))   #绑定IP和端口号,传一个元组,元组第一个元素是IP第二个元素是端口号
sk.listen()  #进行监听

客户端与服务端二者通信

以上代码就已经在客户端与服务端搭建了联系,浏览器输入http://127.0.0.1:8000并确定就可以理解为一个手机(客户端)拨通了一个客服(服务器)的电话。而代码sk.listen()只是表示客服上线了在带命中,并不表示客户端只要发出请求服务器就能接收到,接下来的代码才是二者的通信:

while True:
    conn,addr = sk.accept()  #接收socket客户端连接(手机拨号后客服接电话了)
    data = conn.recv(1024)   #接收socket客户端数据
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')   #以字节形式向客户端发送消息

以上代码已经实现了客户端和服务端的通信,但是data和conn.send()所发送的内容都是HTTP请求或响应的消息。其格式如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码块中conn.send()的作用是向客户端发送消息,所以发送消息的第一句只能是按照HTTP响应消息的格式发送响应头第一行信息,此时的浏览器界面上是看不到任何消息的。响应头的其他字段和值可以省略,所以想要向客户端发送其他消息再调用一次conn.send()即可。

Web开发的核心功能

如果说上一部分是让客户端与服务端之间拨通了电话,相互说了一声“喂~”,那么接下来这部分就是二者实际的交互。服务器的背后虽然由研发维护人员,但是不可能真的由一个客服人员在线等待客户端的请求再反馈。这必定是用代码来写的一个逻辑关系——当服务端接收到客户端的请求后做出将返回什么样响应的逻辑关系,而这个逻辑关系就是Web开发的核心功能。

import socket

def indexes(url):
    with open('index.html','r',encoding='utf-8') as f:
        rd = f.read()
        rd = rd.replace('$@index$@','首页')
    return bytes(rd,encoding='utf-8')
def tests(url):
	with open('test.html','r',encoding='utf-8') as f:
        rd = f.read()
        rd = rd.replace('$@test$@','测试')
    return bytes(rd,encoding='utf-8')
def fun404(url):
	ret = '<h1>not found!</h1>'
    return bytes(ret,encoding='utf-8')

#建立url与函数名的对应关系
url_func = [
    ('/index/',indexes),
    ('/test/',tests)
]

sk = socket.socket()
sk.bind(('127.0.0.1',8000))
sk.listen()

while True:
    conn,addr = sk.accept()
    data = conn.recv(1024)
    if not data:
        continue
        
    #获取请求路径信息(不懂看HTTP请求格式)
    data_str = str(data)
    line = data_str.split('\r\n')
    v1 = line[0].split()
    url = v1[1]
    
    #url_func对应关系,确定反馈信息并反馈
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    func = None
    for i in url_func:
        if i[0] == url:
            func = i[1]
            break
    if not func:
        func = fun404
    rep = func(url)
    conn.send(rep)
    conn.close()

再附上代码块中需要的两个HTML文件

<html lang='en'>
    <head>
        <meta charset='utf-8'>
        <title>index页面</title>
    </head>
    <body>
        <h1>$@index$@</h1>
    </body>
</html>

test.html文件同上index.html,不在重复。这里简单地说明一下,之所以在主题一级标签的内容两边都加上$@符号是当作占位符使用,毕竟python的占位符%或者{}在其他语言中都有另外的意义。

Web框架的3个核心功能功能

本文打这里,用socket实现Web开发框架就已经全部完成了。概括起来就是python中Web框架一般实现的3个核心功能:

1、收发消息(socket功能)

2、根据用户不同路径执行不同的函数

3、从HTML文件中取出内容,并且完成字符串的替换

目前python主流的Web开发框架有Django、Tornado和Flask三种,也是各有不同地实现上述核心功能的两到三种。如Django就是实现了第二三种功能,这两种功能可以很容易地通过编写代码或配置来实现,第一种功能则是以第三方工具来实现的。

符串的替换

目前python主流的Web开发框架有Django、Tornado和Flask三种,也是各有不同地实现上述核心功能的两到三种。如Django就是实现了第二三种功能,这两种功能可以很容易地通过编写代码或配置来实现,第一种功能则是以第三方工具来实现的。

图片来源:拍摄于书籍《Django实战Python Web典型模块与项目开发》(张晓 著)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多