在IT行业有很多前辈针对固定的一些问题设计出了固定的解题套路
设计模式总共有23种
设计模式总共分为三类
创建型
结构型
行为型
设计模式之单例模式
类加括号调用多次只允许产生一个对象
使用元类干预对象的创建过程
class Mymetclass(type):
#记录
instance =None
#在元类中通过双下call来定制 对象的产生
def __call__(self,*args,**kwargs):
#先判断 是否已经创建过对象
if self.instance:
renturn self.instance
#没有则 直接执行对象创建
res=super().__call__(args,kwargs)
#创建 记录下 下次可以直接拿
self.instaance=res
return res
#修改 类的元类
class Myclass(metaclass=Mmetclass):
def __init__(self,name):
self.name=name
pickle模块与json模块很想 都是用来做序列化 反序列化的
并且 pickle模块支持python所有数据
但是 pickle模块 不支持跨语言传输 只能python自己跟自己玩 兼容性不好
为了比较方便编写选课系统 我们需要将对象保存到文件 所以需要用该模块
class Myclass:
def __init__(self,name):
self.name=name
def choice_course(self):
print('选课系统')
obj=Myclass('jason')
import pickle
with open(r'a.txt', 'wb')as f:
pickle.dump(obj, f)
with open(r'a.txt', 'rb')as f:
res = pickle.load(f)
软件开发架构
编程写项目之前需要遵循代码层面上的规范 (代码运行的流程、环节、步骤)
C/S架构
计算机上下载的各个互联网公司的app软件本质其实是客户端
下载一个个客户端的目的就是为了体验对应的服务端的服务
客户端可以看成是即将去消费的客人
服务端可以看成是给客人提供服务的店
服务端应具备的特征
架构的优劣势
优势:下载对应的应用客户端可以在客户端软件内高度定制相关服务
劣势:使用前必须先下载客户端
B/S架构
b/s架构本质也是c/s架构
通过浏览器来充当客户端 用于想体验服务但不需要下载指定的客户端
架构优劣势
优势:不需要下载客户端 能够快速体验服务
劣势:定制花里胡哨的功能比较繁琐
发展趋势: 统一接口原则
微信
里面有很多小程序 可以直接体验其他服务
支付宝
里面有很多小程序 可以直接体验其他服务
后续就是cs和bs交错私用 避免各自的劣势
可以方便用户使用 更重要的是可以给自己圈用户 便于后期收割
网络编程简介
基于胡来女王编写代码 程序可以实现远程数据交互
网络编程的目的
网络编程的本质是为了了解计算之间远程数据交互
网络编程的意义
学习完网络编程之后 我们就可以编写一个C/S架构软件
网络编程起源
完了过编程由美军开发 在没有网络编程之前 计算机数据交互 都需要 人工通过硬盘来远程传递数据
网络编程的要求
计算机想要实现远程数据交互 首要条件就是要有物理层连接介质
规定了计算机 涉及到数据远程交互的时候 必须要经过的部件/流程
所有计算机在涉及到网络传输这块必须要有相同的零部件
OSI七层协议
| OSI七层协议 |
|---|
| 应用层 |
| 表示层 |
| 会话层 |
| 传输层 |
| 网络层 |
| 数据链路层 |
| 物理连接层 |
应表会传网数物
每一层都有各自的功能和规范
数据发送出去的时候 是从上往下走的
数据接收回来的时候 是从下往上走的
我们按照从下往上的顺序来研究
保证物理连接介质的条件 传递电信号(主要研究网络线的情况)
规定了电信号的分组方式
规定了每台计算机都必须要有一块网卡
寂然mac地址相当于电脑身份证号 也就意味着 可以根据该地址查找到计算机 (可以基于mac地址 实现数据交互)
交换机
能够让接入交换机的多台计算机实现彼此互联
以太网通信(mac通信)
原理
有了交换机之后 根据电脑的mac地址 就可以实现数据几哦啊换
广播:先在交换机中吼 所有接入交换机的设备都能收到
单播:只有被查找设备 才会回复相应信息
缺陷:
mac地址通信权限仅限于局域网
接入交换机的设备过多可能会造成广播风暴
广播风暴:类似于所有人同时吼
局域网
有某个固定区域 组成的网络
广域网可以看成是更大区域的局域网
路由器
将多个局域网连接到一起的设备
IP协议
规定了任何接入互联网的计算机都必须要有一个IP地址
IP地址
IPv4:点分十进制
最小:0.0.0.0
最大:255.255.255.255
随着社会的发展 同时能够上网的人越来越多 也导致 上述的地址不够分了
IP特征
每个IP都自带定位
IP代理
端口协议:规定了一台计算机上的每一个正在运行的应用程序都必须有一个端口号,端口号相当于是让计算机用来管理多个应用程序的标记
端口号特征
IP+PORT
IP:用于表示全世界任意一台接入互联网的计算机
PORT:用于标识一台计算机上的某个应用程序
IP+PORT:用于标识全世界任意一台接入互联网的计算机上的某一个具体的程序
什么网址
网址(URL):统一资源定位符
url的本质
其实就是IP+PORT(IP:port)
www.baidu.com>>>124.12.11.232
端口协议中常用的两种协议
TCP协议 与 UDP协议
规定了数据传输所遵循的规则
数据传输能够遵循的协议有很多TCP和UDP只是比较常见的两个
三次握手:建立双向通道
洪水攻击:就是同时让大量的客户端朝服务端发送建立TCP连接请求
四次挥手:断开双向通道,中间两部不能合并 (需要检查的时间停顿,检查是否还有数据没有发送完)
基于TCP传输非常安全 因为有双向通道
TCP类似于打电话:你一句 我一句 有来有往
UDP类似于发短信:只要发送了 不管别人看没看到也不管回不回复
主要取决程序员自己窜用什么策略
常见的协议有:HTTP、HTTPS、FTP…
基于文件类型套接字家族
套接家族的名字:AF_UNIX
基于网络类型的套接字家族
套接字家族的名字:AF_INET
要求
消息自定义
利用input接收用户数据
循环通信
给数据交互环节添加循环即可
循环通信
给数据交互环节添加循环即可
服务端能够持续提高服务
不会因为客户端 断开连接而报错
异常捕获 一旦客户端断开连接 服务端结束通信循环 遇到连接处等待
服务端
import socket
import json
#创建一个socket 对象
sever = socket.socket()
#绑定一个固定的地址(ip/port)
server.bind(('127.0.0.1,8080')) #建立回环地址
#办理按揭池
sever。listen(5)
#准备就绪 等待客户端来访问
#添加循环 让服务端每次结束客户端 连接接触都能回归位等待访问状态
while True:
sock,address = sever.accpet()
#sock 是双向通道 addresss是客户端地址
print(sock,address)
#数据交互
#添加循环 让服务端 能够自定义返回数据
while True:
try:
sent_data = input('请输入发送的数据>>>').strip()
#防呆 防止不输入内容
if len(sent_data)==0:
continue
sent_data = bytes(sent_data.'utf')
sock.sent(sent_data)
#接收 客户端发送的数据 (1024)bytes
data = sock.recv(1024)
data = str(data,'utf')
print(data)
#当客户端断开吼 异常捕获
except Exception:
break
客户端
import socket
#产生一个socke对象
client = socket.socket()
#连接服务器 (拼接服务端的ip和port)
client.connect(('127.0.0.1',8080))
#数据交互
#添加循环 能够让客户端 重复发送数据
while True:
data = client.recv(1024)
data=str(data,'utf')
print(dtata)
#朝服务端发送数据
sent_data=input('请输入要传输的数据>>>').strip()
sent_data=bytes(sent_data,'utf')
client.send(sent_data)
半连接池
主要是为了做缓冲 避免太多的无效等待
server.listen(5)#参数5 表示 等待访问的客户端数 超过这个数据 那么就会使那个客户端报错
TCP特性
流逝协议:所有数据类似于水流连接在一起的
数据量很小 并且时间间隔很多 那么就会自动组织到一起
recv
我们不知道即将要接收的数据量很大 如果知道的话 不会产生黏报
利用struct模块
struct模块 无论数据长度是多少 都可以帮你打包成固定的长度
然后基于该长度 还可以反向解析处真实的长度
import struct
info = 'hello啊 树哥'
print(len(info))
#将数据原本的长度打包
res=struct。pack('i',len(info))
#打包之手的长度为4
print(len(res))
#将打包之后的固定长度 为4的数据拆包
ret = struct.unpack('i',res)
#又得到了原本的数据长度
print(ret[0])