目录
一、软件开发架构
我们在学习ATM跟选课系统的时候了解到了三层架构方式,这其实也是一种开发的架构方式,总得来分我们可以分成两种大类的架构方式:
c/s架构
c是客户端的意思
s是服务端的意思
b/s架构
是一种另类的c/s架构
b是浏览器
s是服务端
这里的浏览器其实也是一种客户端,因此我们称它为另类的c/s架构
优劣势
c/s因为使用的时候需要下载专属的客户端,比较适合进行一些定制功能的创建,但是使用的时候需要下载客户端,
b/s端的优势就是不用下载客户端,使用浏览器就能使用上各个软件的对应功能,但是在浏览器上定制服务的时候需要遵循一定的规则,导致了不能进行私人订制的功能,大家的功能都看起来差不多。
二、网络编程
网络编程就是通过网络进行编程,实现数据的远程交互。数据的远程交互就是开发网络编程的目的
网络变成的民用计数都是从军用领域中淘汰下来的,网络变成最早出现在美国的军事领域中。
网络变成的要求是必须要有物理介质,这一点我们在平时的生活中也可以体会到,上网需要用到网线或是网卡。
三、OSI七层协议
简介
作用:规定了所有计算机在远程数据交互的时候必须遵循一定的的规则,必须要有相同的物理设备。
七层名称:
应用层
表示层
会话层
传输层
网络层
数据链路层
物理连接层
其中前三层可以整合成应用层
后两层可以整合成网络接口层
接收数据的时候从下往上,传输数据的时候从上往下
物理层
规定使用的物理设备,同时也呼应上面说的网络编程需要有物理介质
数据链路层
作用1:规定二进制的划分(传输数据的时候数据都是二进制没有划分内容)
作用2:规定计算机在出厂的时候需要带有一个唯一的以太网/mac地址,由12为16进制数组成。前六位是厂商编号,后六位是生产流水号。
网络相关的一些名词
交换机:连接一些计算机组成一个局域网
广播:一台计算机在局域网内首次向一个对象建立连接请求的时候会向所有的局域网内的计算机发送建立连接的请求。
单播:当被请求对象受到连接请求后就会跟发起请求的计算机进行一对一的交流
广播风暴:很多台计算机同时处于首次查找的状态发送请求会形成广播风暴
局域网:交换机组成的,范围较小的网络
广域网:范围较大的局域网
互联网:所有的网络连接在一起组成了互联网
路由器:用于局域网之间的连接
网络层
介绍了一些网络名次之后我们介绍网络层
网络层中规定了ip这一概念,所谓的数据链路层的以太网地址算是一个固定的物理地址,ip就相当于是一个动态分配的地址,同时ip分成IPv4和IPv6
IPv4是目前的使用的主流,ipv6正在慢慢普及
传输层
传输层提到的是PORT(端口)的相关协议
当我们开启一个应用的时候就会给他动态分配一个端口号
接着是提到了URL(也叫域名,俗称网址),它是由IP+PORT组成的,但是由于他在使用的时候非常难记,导致了域名,也就是网址的产生,我们在使用的时候基本都用的是网址,这里的运行流程其实是浏览器把域名解析称IP+PORT来访问对应的地址,同时我们可以直接使用IP+PORT来访问。
传输层
这里主要是两个传输协议:TCP和UDP协议
TCP
tcp就相当于打电话,两者数据传输的时候需要互相回应。
我们在tcp协议传输数据的时候是用到了双通道传输数据的
创建通道的时候用到了三次握手
第一次握手:客户端发送建立客户端向服务端传数据的请求,同时附带上自己的初始化序列号(是一种唯一标识,分辨客户端身份)
第二次握手:服务端受到请求返回同意的信息,同时请求建立服务端向客户端发送信息的通道
第三次握手:客户端发送同意的回应双方成功建立传输数据的双向通道。
tcp传输数据可靠并不是因为双向通道的存在,传输数据的时候会在发送端复制一份要发送的信息,在接收端返回受到的信号之前会在一定时间内频繁发送,直接受到接收端的信息后才会停止发送,并删除复制出的信息
洪水攻击
短时间内有大量的客户端请求建立连接,导致服务端没有办法回应,无法建立双向通道
断开双向通道的时候用上了四次挥手
第一次挥手:客户端向服务端发送断开连接的请求
第二次挥手:服务端接收客户端的请求并给出回应,这时客户端向服务端传输数据的通道就断开了,到那时这时候会处于time_wait状态,服务端会确认自己还有没有信息需要传递给客户端
第三次挥手:当服务端确认完没有需要发送给客户端的信息时就会发送断开服务端向客户端传输数据的通道的请求
第四次挥手:当客户端收到了服务端的请求后给出回应,双方连接彻底断开。
UDP
udp就相当于是发短信,只管发送信息
应用层
这里存在很多协议比如http、https、ftp、dns、dhcp
四、socket模块
当我们在python中想要创建服务端和客户端的时候需要用到socket模块
服务端用到的代码
server_side = socket.socket()如果需要改成别的协议需要用关键字设置(type=socket.SOCK_DGRAM) # 声明udp协议,默认情况下是TCP协议
server_side.bind('IP地址', 端口号)
创建服务端
server_side.listen(5)
设置半连接池,作用就相当于消费的时候进行排队
sock,add = server_side.accept()
接收客户端信息
data = sock.revc(1024)
接收客户端发送的信息,发送的信息的二进制数不能超过括号内的数量,溢出的不接收
sock.send()
返回给客户端的信息
sock.close()
关闭跟客户端的连接
server_side.close()
关闭服务端
客户端
client = socket.socket()
client.connect('IP',端口号)
与服务端建立连接
client.send()
发送信息
data = client.revc(1024)
接收服务端的回应
接着老师进行了一些优化
比如给两边的代码套上循环可以重复运行
然后用len判断发送的信息的长度,防止因为客户端发送空消息导致服务端报错
接着是消息发送的时候使用input自定义
当服务器多次重启的时候会出现端口号被占用的情况,这时候windows电脑会直接报错,mac电脑会在一段时间内发送空消息然后报错,处理方式有两种,一种是更改端口号,第二种加一行代码:
from socket import SOL_SOCKET,SO_REUSEADDR
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
当客户端被强制关闭的时候会导致服务端异常报错,这时候我们使用异常处理来让他避免报错。
五、黏包现象及解决方式
当我们在客户端发送三次短数据,服务端接收三次短数据,同时recv的参数设置成大一点,这时候运行代码会发现三次数据都被第一次的recv接收了
这是因为tcp协议是一个流式协议,可以当成流水一样,当他遇到短数据,并且发送间隔短的时候,就会把他们打包起来一并发送,算是一种优化,但是带来了黏包问题。
处理方式有两种,一种是手动设置revc的参数
另一种是使用字典传递出参数告诉服务端要发送文件的大小,再来接收
这里就要用到struck模块
他可以把二进制数据变成固定的长度打包,同时又可以解压出来
pack是打包的关键词
unpack是解压的关键词
我们在解决黏包问题的时候首先是获取字典的二进制长度,然后发送给服务端,服务端接收后获得了字典的文件大小,然后接收字典,通过字典获取文件的大小然后再来接收文件。
六、并发编程理论
首先讲了一下历史
最早的时候的计算机用的是穿孔卡片来传输指令运行电脑,导致了cpu虽然效率很高但是没法合理应用
于是有了后面的批处理的方式,先用磁带存储指令,然后让计算机读取,因为是磁带,所以可以存很多程序员的代码一次性读取进去。
批处理又分成联机批处理和脱机批处理,
联机就是放磁带传指令,脱机的话就是用到了卫星站来接收再传递给计算机,可以实现较远举例的传输。
七、多道程序设计计数
当我们在学习并发编程的时候会涉及到多道程序计数
他其实很简单,分成单道和多道
单道就是运行程序的时候排队,如果到了input等需要等待的地方,就等待不做别的时候,获取了之后再运行后续的代码
多道就是我在获取input的时候不干等,我去继续运行后的代码来节省时间提高工作效率,放到计算机中就是磁盘读取了前一个程序的代码后不休息,直接在cpu运行前一个程序的时候去读取后一个程序的代码。
切换
当我们在运行程序的时候不可能说根据先来后到的顺序一直运行完下一次才接着运行别的程序,所以当程序运行一段时间cpu就会切换到别的程序运行,当程序运行到I/O操作(输入输出、time.sleep等操作)的时候cpu也会切换到别的程序运行
保存状态
当cpu离开,不给一个应用程序继续使用的时候会保存他的工作状态。
八、进程理论
进程和程序的区别
存在磁盘中的代码叫程序
读取到内存中通过cpu运行起来的代码叫做进程
进程的调度算法
1、FCFS
cpu根据进程的先后顺序来服务,中间不能插队不能同时服务,效率低
2、短作业优先调度
耗时短的进程优先处理,但是当短进程很多的时候就会导致耗时长的进程长期得不到处理,也不合理
3、时间片轮转法+多级反馈队列(目前用的)
时间片轮转法可以这样理解,比如把一秒平均分配给每个进程
多级反馈队列就是把进程根据耗时分级,耗时长的优先级低,短的优先级高,但是耗时长的一次性分到的时间会多一些,新的进程优先级在最高那层,并且会优先处理。
进程的并行与并发
并行就是一个cpu对应一个进程,所有进程同时进行(因为一人一个cpu互补影响)
并发就是一个cpu运行很多的进程,这就需要用到上面的调度算法给每个进程分配时间让他们同时运行起来
今后追求的通常都是高并发,成本低,比较现实。
进程的三状态
就绪态、运行态、阻塞态
同步异步
同步
进程运行的时候根据顺序执行,中间不运行别的程序
异步
进程运行到I/O操作的时候就去运行别的程序
阻塞非阻塞
阻塞和非阻塞主要在于并发状态下有没有用上cpu,用上cpu了就处于非阻塞状态,没得用就是阻塞状态
同步异步阻塞非阻塞的综合使用
同步阻塞
同步非阻塞
异步阻塞
异步非阻塞
今后用的都是异步非阻塞,别的效率低,在判断的时候根据上面的条件进行判断
创建进程的多种方式
双击程序图标打开进程
在进程内打开新的进程
目前常见的就是这两种
在python中创建进程要用到multiprocessing模块
一种是定义成函数然后创建函数的时候调用方法把函数放到子进程中运行
一种是用面向对象的方式重写process类用上派生方法,让创建的对象可以使用process的方法创建子进程,内部的run方法在创建进程的时候会直接运行
进程间的数据隔离
因为windows中创建子进程相当于把被执行文件当成模块导入了,mac中相当于是复制了一份代码放到子进程中运行,这就导致了在子进程中的数据相当于是存在与另一个py文件中
子进程和主进程两者互相独立
join方法
使用start可以让子进程跑起来,用上join后就可以让子进程从异步变成同步的方式来运行
IPC机制
提到了Queue方法
作用是产生一个多进程键的数据传输队列
生产者消费者模型
这是一个概念
产生数据的进程就是生产者
拿数据的进程就是消费者
然后生产者把商品放到货架上消费者从货架上拿商品,这个货架就相当于IPC(多进程间传输数据的队列)
小知识
multiprocessing还有很多小方法
getpid获取进程号
getppid获取创建这个进程的进程的进程号
current_process().pid也是查看进程号
.terminate()终止进程
.is_alive()查看进程是否还在运行
cmd中输入tasklist可以查看目前进程的进程号
守护进程
主进程跟守护进程是一个绑定关系,主进程没了,就会导致守护进程跟着消失,反之并不会导致主进程消失,但是在把一个进程设置成守护进程的时候,如果先把他运行了就不能设置成守护进程了
僵尸进程
当一个进程运行结束后,并不会立刻删除内存中的所有信息,而是会存留几秒,供父进程获取信息
孤儿进程
当一个子进程的父进程意外关闭的时候他就变成了孤儿进程,在系统中会有专门的进程来接收这些子进程
进程数据错乱
用的例子是买车票的例子,当我们用很多客户端去抢一张车票的时候,因为信息的滞后性导致所有的人都显示成了买到了车票,这导致了数据的错乱,因为只有一张票,处理方式就是用互斥锁