python

OSI 七层协议

  • 物理层 ,数据链路层 , 网络层 ,传输层 ,会话层, 表示层, 应用层
说明
物理层 主要用来定义物理设备标准,用来传输比特流(0和1 的电流表示)
这一层的数据叫做bite(比特)
数据链路层 定义如何让格式化数据进行传输,以及如何让控制对物理介质进行访问
这一层通常还会提供错误检测和纠正,以确保数据的可靠传输
网络层 对位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择
internet的发展使得从世界各站点访问信息的用户数量大大增加,而网络层
正是管理这些连接的层次
传输层 定义一些传输数据的协议和端口号(www端口80等),它的作用主要是将从下层
接收到的数据进行分段和传输,到达目的地址后再将数据进行重组,常常把这一
数据叫段
会话层 通过传输层(端口号: 传输端口与接收端口)建立数据传输的通路,主要是在系统
之间发起会话或者接收会话请求(设备之间需要相互认识可以是IP也可以是
MAC或者是主机名)
表示层 可以确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取
应用层 对表示层的信息进行解码,获取响应的信息

四层模型

  • 应用层,传输层,网络层, 物理层

五层模型

  • 应用层,传输层,网络层,链路层,物理层

各层协议

协议
应用层 HTTP, FTP ,TFTP ,SMTP ,SNMP ,DNS ,TELENT ,HTTPS ,POP3 ,DHCP
表示层 数据的表示,安全,压缩 JPEG,ASCII,DECOIC,加密格式
会话层 建立,管理,终止会话 选择传输层协议
传输层 TCP/UDP协议 TCP 流式套接字 UDP 数据报式套接字
网络层 ICMP IGMP IPv4 IPv6 进行逻辑地址寻址 ARP RARP

三次握手

  1. 客户端向服务器发起连接请求(问是否可以连接)
  2. 服务器接收到请求后进行确认(允许连接)返回报文(一定的数据消息)
  3. 客户端收到许可,建立连接

四次握手

  1. 主动方发送报文告知被动方要断开连接
  2. 被动方返回报文,告知受到请求,准备断开
  3. 被动方发送报文给主动方告知准备就绪可以断开
  4. 主动方发送报文确定断开

OSI 模型特点

  • 高内聚,低耦合
  • 每一层之间的功能单一,使用通用的接口,
  • 模块之间的关联和影响尽量减少

TCP UDP

区别 TCP UDP
传输形式 字节流式 数据包式
粘包 不会
网络传输 对网络传输要求较高 对网络传输要求较低
可靠性 较高 较低
使用方式 客户端端口
使用recv,send,connect
客户端
使用recvfrom,sendto
建立连接 TCP 使用connect((ip, port)) UDP 使用 sendto 兼连接功能
  • 创建TCP套接字流程

    1. 创建套接字对象 SOCK_STREAM
    2. 设置host port
    3. 设置套接字为监听
    4. 阻塞等待间接请求 accept
    5. 接收或发送信息 send recv
    6. 关闭套接字
  • 创建UDP套接字流程

    1. 创建套接字对象 SOCK_DRGAM
    2. 设置host port
    3. 收发信息 sendto recvfrom
    4. 关闭套接字

套接字常用方法

方法 说明
socket.gethostname DESKTOP-BOOGIMN
socket.gethostbyaddr’localhost’ ‘DESKTOP-BOOGIMN’, [], [‘::1’]
socket.gethostbyname’localhost’ 127.0.0.1
socket.gethostbyaddr’127.0.0.1’ ‘DESKTOP-BOOGIMN’, [], [‘127.0.0.1’]
socket.gethostbyaddr’http://www.baidu.com' 报错
转换ip地址 ipv4,ipv6
socket.inet_aton’127.0.0.1’ b’x7fx00x00x01’
socket.inet_ntoab’x7fx00x00x01’ 127.0.0.1
socket.inet_ptonsocket.AF_INET, ‘127.0.0.1’ b’x7fx00x00x01’
socket.inet_ntopsocket.AF_INET, b’x7fx00x00x01’ 127.0.0.1
socket.inet_ptonsocket.AF_INET6, ‘127.0.0.1’ OSError: [WinError 10022] 提供了一个无效的参数
获取主机信息
socket.getservbyport80 http
socket.getservbyname’FTP’ 21
socket.getservbyname’Ssh’ 22
socket.getservbyname’Https’ 443
socket.getservbyport23 telnet
socket.getservbyport143 OSError: port/proto not found
socket.getservbyport53 domain DNS—UDP
ipconfig cmd命令 查看ip 及 mac地址
ifconfig bash命令 查看ip 及 mac 地址

UDP套接字

  • 客户端不需要指定端口号和ip地址
  • 在连接服务器时,电脑自动指定为客户端绑定一个端口
  • 因此客户端连接服务器时,需要首先发送信息确认连接

使用地址,无论是 TCP ,还是 UDP ,地址都使用元组的形式进行传参

soc = socket()
soc.bind(('localhost', 8888))

套接字方法

s = socket()
方法 说明
s.fileno() 文件操作符
s.type tcp,还是udp
s.family AddressFamily.AF_INET协议类型,
s.getsockname() 获取主机地址
s.getpeername() 获取accept接收到的地址
s.setsockopt(level,optname,value)
    # 协议中的每一层为level项, optname 为变量名称, value 为设定的值
s.getsockopt(level, optname)
    # 获取常量名

多任务处理

IO 密集 与 计算密集

  • 在计算机中,处理网络,文件类,CPU利用率很低的事件,被称为IO事件
  • 处理 数值计算,视频音频的大规模处理类的事件被称为cpu密集或计算密集

IO分类

  • 阻塞IO
  • 非阻塞 IO
  • IO多路复用
  • 事件 IO
  • 异步 IO

多任务处理

  • 并发

    • 计算机处理多个任务时,内核在任务间不断的切换,达到好像在同时运行的效果
  • 并行

    • 多个计算机核心同时处理多个任务,各个任务之间运行没有关系,是并行的关系

进程

  • cpu处理的单位,拥有独立的资源(内存,cpu时间片,相关信息等),是计算机运行时的基本单位,
  • 在理论上进程中有一个线程,当有多个线程共存于进程时,进程的会分配一小部分资源给线程
  • 理论上

僵尸进程

  • 子进程先于父进程退出,但父进程没有处理子进程的退出,就退出了,使得子进程的一部分资源无法被资源回收
  • 僵尸进程会占用系统资源,尽量避免僵尸进程的产生
  • 避免僵尸进程
    1. 创建二级子进程
    2. 让父进程处理子进程的退出 (wait函数, waitpid 函数)

孤儿进程

  • 父进程先于子进程退出,使得子进程无法没有父进程,就成为了孤儿进程
  • 孤儿进程并不是没有父进程,系统进程会收养子进程,成为安全的进程

multiprocessing Process 类 Pool 类

  • Process(name, target, args, kwargs)

    • name : 给创建的进程起一个名字 默认为 Process -1
    • target: 使用进程的函数
    • args,kwargs: 元组传参, 字典传参
  • p.start()

    • 启动子进程,此时进程被创建,是运行态
  • p.join(s)

    • 阻塞等待默认子进程的退出,回收子进程
    • s 默认为阻塞, 设置 s 为超时时间,停止阻塞
  • 如果使用多个进程时,有两种方法

    1. 在start 后执行程序
    2. 再次创建一个进程,即同时有三个进程
      1. 父进程负责回收子进程
      2. 两个子进程互不干扰
  • Process 的属性和方法

属性或方法 说明
p.is_alive() 查看进程是否存在
p.name 查看进程名
p.pid 查看该进程的pid
p.daemon 守护进程,默认为 False,设置为 True 时,进程运行完毕会自动回收
替代join 功能
os.getpid() 查看进程pid
os.getppid() 查看父进程的pid

多进程优缺点

  • 优点

    1. 并行执行多个任务,效率较高
    2. 创建方便
    3. 运行独立,不受其他进程影响
    4. 数据独立,不存在安全问题
  • 缺点

    1. 进程的创建与销毁需要消耗大量资源
    2. 进程消耗的资源较多,相当于多线程的20倍

进程池技术 Pool 类

  • 多个进程创建与销毁,需要系统分配资源进行管理,运行效率较低,消耗的资源也较多
  • 使用进程池的方式,针对大量进程的操作时,节省系统资源

使用方式

  • p = Pool(n)

    • 创建进程池对象
    • n 表示一次进程处理的进程数量,一般与cpu 核心数相等
  • p.apply_async(func, args, kwargs)

    • func 要放入进程池的事件函数
    • args 元组参数
    • kwargs 字典参数
  • 放入进程池函数的方法有很多,map,map_async, apply

  • p.close()

    • 停止添加进程池函数,并使得进程池开始运行
  • p.join()

    • 阻塞等待所有进程退出,并回收所有资源

进程间通信 IPC

管道通信

- multiprocessing  Pipe
- f1, f2 = Pipe(duplex)
    - duplex == 双工
    - 单工 (设置为 False)
        单工就是指A只能发信号,而B只能接收信号,通信是单向的,就象灯塔之于航船——灯塔发出光信号而航船只能接收信号以确保自己行驶在正确的航线上。
    - 半双工 (不使用)
        指一个时间段内只有一个动作发生,举个简单例子,一天窄窄的马路,同时只能有一辆车通过,当目前有两量车对开,这种情况下就只能一辆先过,等到头儿后另一辆再开,这个例子就形象的说明了半双工的原理。早期的对讲机、以及早期集线器等设备都是实行半双工的产品。随着技术的不断进步,半双工会逐渐退出历史舞台。
    - 全双工 (设置为 True)
        Full-Duplex Transmissions 
        指交换机在发送数据的同时也能够接收数据,两者同步进行,这好像我们平时打电话一样,说话的同时也能够听到对方的声音。目前的交换机都支持全双工。
    - 设置为False时,f1 只能 读, f2 只能写
- f1.recv()
    - 读取信息(每次读取一条)
    - 默认阻塞
- f2.send(data)
    - 写入信息 (字符类型,任意类型)

消息队列

- multiprocessing Queue

- q = Queue(maxsize = 0)
    功能 : 创建一个消息队列
    参数 : maxsize 默认为0     表示根据系统分配空间存储消息
                                     > 0 表示队列最多存放多少条消息
    返回值 : 返回消息队列对象

- q.put(data,[block,timeout])  
    功能 : 向队列中存放消息 
    参数 : data      表示存入的消息 (支持Python数据类型)
         block     默认为True  表示阻塞【当队列满时会阻塞】
                   设置为False  表示非阻塞【当队列满时不阻塞,会报异常】
         timeout    当block为True时表示超市时间

- data = q.get([block,timeout])
    功能 : 从队列中获取消息
    参数 : block     默认为True  表示阻塞【当队列空时会阻塞】
                   设置为False  表示非阻塞【当队列空时不阻塞,会报异常】
    返回值 :取出的消息

- q.full()
    功能: 判断队列是否为满  满返回True

- q.empty()
    功能: 判断队列是否为空  空返回True

- q.qsize()
    功能: 得到当前队列中消息的个数

- q.close() 
    功能: 关闭队列

共享内存

- 在内存中开辟一段空间,存储数据,多个进程可见,每次写入共享内存
- 对内存格式化较少,存取速度快,
- 需要对共享内存加锁,才能保证数据安全
- from multiprocessing import Value,Array
- obj = value(ctype, obj)
    - c 类型对照 ctype表
    - signed int ‘i’
    - char 'c' char
    - 
- obj.value
    - 表示共享内存中的值,对其修改或者使用即可共享内存的值

- Array
    - obj = Array(ctype, data)
        - ctype :: c类型
        - obj :: 存入共享内存的数据
            1. 列表    将 列表存入共享内存, 列表内中数据类型需要一致
            2. 正整数  则表示开辟一个多大的序列空间
    - 在使用时, 需要将obj 作为参数传入 进程中, 方能进行操作

            arr = Array('i', [1, 2, 3, 4, 5])
            pro = Process(target=client, args=(arr, ))

信号

- 在linux 使用体验较好
- import signal
- signal.signal(signum, handler)
    - signum 处理的信号   kill -l 查看linux 信号
    - SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM  windows常用信号
    - handler 接收该信号的处理方式
        - SIG_DFL    默认处理方式
        - SIG_iGN    忽略【ignore】
        - function 自定处理该信号
            - func(sig, frame)  # 自定信号传入两个参数
                - sig   信号值
                - frame 信号对象
- signal.alarm(n)
    - 过 n 秒后发送 SIGALRM 信号
- signal.pause()
    - 等待信号
  • 信号量

    • sem = Semaphore(2) # 创建信号量对象,设置初始信号量

      def fun():
          print('进程%d等待信号量'% os.getpid())
      
          sem.acquire()  # 信号减一 
      
          print('进程%d消耗信号量'% os.getpid())
          sleep(5)
      
          print('进程%d添加信号量'% os.getpid())
          sem.release()  # 信号加一
      
    • sem.get_value() 获取当前信号量

    • sem.acquire()

      • 功能 :将信号量 减一 信号量为0时调用会阻塞
    • sem.release()

      • 功能 :将信号量 加一
    • 注意:
      • 在 windows 上使用需要传参进函数方能使用
      • 在 linux 不需要
  • 套接字

同步 异步

  • Event事件

    • 创建 事件对象

      e = Event()
      

      -提供事件阻塞

      e.wait([timeout])
      
    • 事件设置:e处于设置状态,e.wait不再阻塞

      e.set()
      
    • 事件清除:e处于未设置状态,e.wait则阻塞

      e.clear()
      

同步 互斥

  • 锁 Lock
  • 进程锁 multiprocessing Lock
    • 可与 共享内存 进行配合使用,解决资源共享的问题
    • 进程 与 锁之间的关系,
      • 锁就像一个进程管理器
      • 当一个进程获取到锁后,并进行加锁(acquire),则另一进程会处于阻塞状态
      • 当该进程处理完毕后,进程对锁进行释放(release),另一进程会继续运行
      • 多进程都应该在相同位置加上锁,进行对资源的管理

线程

  • treading import Thread
  • Thread(name, target, args, kwargs)
  • start()
  • join()
  • t.is_alive() 查看线程状态
  • t.name 查看线程名称
  • t.setName() 设置线程名称
  • threading.currentThread() 得到当前线程的线程对象
  • daemon
  • setdaemon(True)

协程

  • 定义:
  • 协程 微线程,协程本质只有一个线程在运行
  • 功能原理:
  • 通过应用层程序,记录上下文栈区,实现在程序执行过程中的跳跃,选择可以不阻塞的部分执行,从而提高IO的执行效率

    优点:
        1、资源消耗很少
        2、无需多线程那样来回切换的开销
        3、无需进行同步互斥操作
        4、IO并发性好
        缺点:
            1、无法利用计算机的多核资源
            2、程序不能够一个客户端单独长时间占有服务器
        底层实现原理:
            yield        协程的基本实现关键字
    
  • 自定义协程

    • greenlet
      • g1 = greenlet(test1)
      • g2 = greenlet(test2) # 创建协程对象
      • g1.switch() # 切换到g2 绑定的程序,
    • gevent