Python基础学习(27)网络编程基本概念 C/S架构与B/S架构 OSI七层协议 包的导入
一、今日内容
- 网络编程基本概念
- C/S 架构与 B/S 架构
- OSI 七层协议
- 包的导入
二、网络编程基本概念
-
mac 地址和 ip 地址
如果在网络中实现数据的传输,那么多台计算机该如何识别我们要传输的计算机呢?首先我们先举个例子,以我们以需要寻找一名同学为例:
- 学校里寻找我们会利用学号,它具有临时、变化等特点;
- 学校外寻找我们会利用身份证号,它是一个人的唯一标识,一般不会发生变化;
所以在计算机中,我们定义了类似的概念:
- mac 地址:在网卡上我们可以看到本机的 mac 地址,它能够唯一标识你这台机器;
- ip 地址:是规定网络地址的协议,它具有临时、变化等特点,广泛采用 ipv4 协议。
-
局域网内传输 —— 交换机
而在普通的局域网中,是怎么实现同一局域网中多台机器传输数据呢?
局域网内部通信主要依靠交换机,而交换机只能够识别 mac 地址,当局域网内有计算机需要在局域网内传输时,它回首先将目标的 ip 地址和自己的 mac 地址传输给交换机,交换机将 ip 地址发送给局域网内的所有计算机,但只有目标计算机会回复并传输自己的 mac 地址,这时交换机已经缓存了传输方和接收方的 mac 地址,数据传输得以顺利进行。而再次传输时,也不需要重新寻找,因为交换机已经缓存了两边的 mac 地址。
这整个过程的协议称为 ARP 协议,即通过一台机器的 ip 地址获取到他的 mac 地址。
-
局域网间传输 —— 路由器
局域网之间的数据传输主要依靠路由器实现:
计算机1 --> 交换机1 --> 路由器网关1 --> 路由器网关2 --> 交换机2 --> 计算机2
而每个局域网都有一个网段:如 192.168.12.0、192.168.13.0 等,对应的是每个局域网内的计算机的 ip 地址可取范围为 192.168.12.0 - 192.168.12.255、192.168.13.0 - 192.168.13.255 等,但不绝对,根据子网掩码才能真正正确判断两台计算机是否在同一局域网内;每个字段对应一个网关,以刚刚的网段为例,对应地网关分别为 192.168.12.1、192.168.13.1。
-
ipv4 协议及 ipv6 协议
-
ipv4 协议:要求 ip 地址由四位点分十进制表示,如 192.169.12.87,每个点隔开的数字都是由八位二进制表示,即只能表示 0 - 255。
-
公网地址:我们需要自己申请购买的 ip 地址;
-
内网地址:保留字段属于内网地址,只存在于内部局域网,由于属于保留字段,不会与公网地址发生冲突;
-
保留字段:从上至下范围越来越大,计算机数量更多、更复杂的局域网会使用更大范围的保留字段:
192.168.0.0 - 192.168.255.255
172.16.0.0 - 172.31.255.255
10.0.0.0 - 10.255.255.255
-
特殊 ip 地址:127.0.0.1 本地回环地址,也属于保留字段。
-
-
ipv6 协议:是一种新提出的用于替代 ipv4 协议的新协议,它可以用冒分十六进制表示,表示范围非常大,号称可以为全世界的每一粒编子边上一个地址。
-
-
子网掩码
我们刚刚了解到,如果只保留最后一个点后的字段,局域网内如果超过 254 台计算机,将无法顺利为其分配 ip 地址,这时我们引入子网掩码的概念,它也是一个 ip 地址,可以用来判断两台机器是否在同一个局域网内,将子网掩码和 ip 地址进行按位与操作,最后结果相同的所有 ip 地址都属于一个局域网。如我们判断下列两个 ip 地址:192.168.13.1、192.168.12.1。
192.168.12.1 # 11000000.10101000.00000110.00000001 255.255.255.0 # 11111111.11111111.11111111.00000000 # 按位与 11000000.10101000.00000110.00000000 = 192.168.12.0 192.168.13.1 # 11000000.10101000.00000111.00000001 255.255.255.0 # 11111111.11111111.11111111.00000000 # 按位与 11000000.10101000.00000111.00000000 = 192.168.13.0 # 所以两个ip地址属于同一局域网
-
获取自己的 ip 地址
- WINDOWS:WIN + R 输入 cmd 打开命令行,输入 ipconfig
- MAC:ifconfig
-
端口 port
一台电脑各个应用在接受和发送消息时都会接受附带相应的端口,来实现多个程序的信息传输,端口的范围为:0 - 65535。
三、C/S 架构和 B/S 架构
一般在应用中,两个程序之间的通讯主要是服务端 server 和客户端 client 之间的通讯。
- 客户端 client:有多个,用户可以自由地打开关闭,需要我们自己安装;
- 服务端 server:只有一个,一般需要 24 小时不间断工作,不需要自己安装。
这种应用之间的通讯架构就是软件的网络开发架构:
- C/S 架构
- C:即 client,客户端,一般是需要安装的;
- S:即 server,服务端;
- 优点:可以离线使用、功能更完善(最主要的好处)、安全性更好。
- B/S 架构
- B:即 browser,浏览器,无需安装;
- S:即 server,服务端;
- 优点:不用安装就可以使用,统一 PC 端用户入口,本身也是 C/S 架构的一种。
四、OSI 七层协议
-
TCP/IP 五层协议概述
OSI( Open System Interconnection ) 将网络通信的工作分为了七层,而 TCP/IP 协议将七层简略的分为了五层,主要包括:
- 五层:应用层(表示层、会话层) 高级语言及软件
- 四层:传输层 portUDPTCP 协议 四层路由器四层交换机
- 三层:网络层 ipv4ipv6 协议 路由器三层交换机
- 二层:数据链路层 mac 地址arp协议 二层交换机网卡
- 一层:物理层 电信号
-
TCP 协议
TCP( Transmission Control Protocol )需要先建立连接,才能够进行通信(类似打电话);
- 特点:占用连接、可靠(消息不会丢失)、实时性高、慢(没有收到回执会一直不断重新发送);
- 应用:语音聊天、视频聊天、远程协助、发邮件;
TCP 建立连接的三次握手和断开连接的四次握手:
# TCP建立连接过程-三次握手 # 全双工通信 # client -----请求连接服务SYN信号-----> server # server ---允许连接ACK信号和SYN信号--> client # client ------允许连接ACK信号--------> server # TCP断开连接过程-四次挥手 # server -----请求断开连接FIN信号-----> client # client ------允许断开ACK信号--------> server # client -----请求断开连接FIN信号-----> server # server ------允许断开ACK信号--------> client # 挥手ACK和FIN挥手不能合并:因为要等待对面数据传输完毕
-
UDP 协议
不需要建立连接,就可以进行通信(类似于发短信);
- 特点:不占用连接、不够可靠(消息因为网络不稳定丢失)、快;
- 应用:在线视频、QQ 消息、微信消息;
五、包(lib)的导入
-
基本导入操作
我们日常使用的很多“模块”其实都是包形式的,如 json、collections 等,我们在使用内置包的时候好像没有发现它与模块在导入与使用中有什么分别,我们现在来介绍一下自定义包的导入方法与规则,首先我们先进行包的数据准备,通过 Python 代码建立下列路径:
import os os.makedirs('glance/api') os.makedirs('glance/cmd') os.makedirs('glance/db') l = [] l.append(open('glance/__init__.py','w')) l.append(open('glance/api/__init__.py','w')) l.append(open('glance/api/policy.py','w')) l.append(open('glance/api/versions.py','w')) l.append(open('glance/cmd/__init__.py','w')) l.append(open('glance/cmd/manage.py','w')) l.append(open('glance/db/models.py','w')) map(lambda f:f.close() ,l)
这时我们已经有了一个包
glance
,我们来尝试按照平时的方法直接导入包:import glance # glance.api.policy() # 报错 print(glance) # <module 'glance' from 'D:\Python\Python_Project\day28\包的导入\glance\__init__.py'>
直接打印
glance
后我们发现,它只是执行包内目录__init__
文件,并不相当于把这个包内所有的文件都导入,那么我们想直接导入某个包下的文件都有什么方法呢?# 方式一 import import glance.api.policy # dazhuang(仍然会执行glanceapi包下的__init__文件) glance.api.policy.get() # from policy.py # 略微简化下: import glance.api.policy as policy # dazhuang(仍然会执行glanceapi包下的__init__文件) policy.get() # from policy.py # 方式二: from glance.api import policy # dazhuang(仍然会执行glanceapi包下的__init__文件) policy.get() # from policy.py # from glance import api.policy # 这样是不可以的,import后面不能带. from glance.api.police import get # dazhuang(仍然会执行glanceapi包下的__init__文件) get() # from policy.py
-
绝对导入和相对导入
我们在包内的模块
__init__
添加:from glance import api....
等,可以实现import glance
从而导入整个包内的模块的功能,但是目录关系的修改会引起报错,所以这被称为绝对导入;而我们在
__init__
添加:from . import api...
等,不会因为glance
目录的修改引起报错,所以又被称为相对导入,但相对导入的模块是无法被直接运行的。所以我们在什么情况下使用绝对导入,又在什么情况下使用相对导入呢?
- 绝对导入:当我们需要写一个功能,这个功能不是直接运行的,而是被别人导入之后使用的,这种情况如果你的这个独立功能能够形成文件夹,文件夹内所有的模块都需要使用相对导入;
- 绝对导入:当我们自己开发一个项目,这个项目有一些文件是需要直接运行的,这种情况适合用绝对导入;