zoukankan      html  css  js  c++  java
  • 网络编程与并发编程总结

    软件开发架构:

    C/S架构:

    Client:客户端

    Server:服务端

    优点:占用网络资源少,软件的使用更加稳定。

    缺点:服务端更新后,客户端也得跟着更新,访问多个服务端需要下载对应的软件,占用客户端计算机的硬件资源大。

    B/S架构:

    Browser:浏览器

    Server:服务端

    服务端:24小时不间断提供服务

    客户端:访问不同的服务端只需要在浏览器输入不同的网址,占用客户端的硬件资源少,但是占用网络资源大,网速比较慢时会不稳定。

    一、网络编程:

    1.互联网协议OSI七层协议

    • 应用层

    • 表示层

    • 会话层

    • 传输层

    • 网络层

    • 数据链路层

    • 物理连接层

      记忆:应表会传网数物

    -物理连接层

    基于电信号发送二进制数据

    -数据链路层

    1)规定好电信号的分组方式

    2)必须要有一块网卡:

    -mac地址:

    12位唯一的16进制字符串:前六位为厂商号,后六位为流水号

    -以太网协议:

    在同一个局域网内通信:

    ​ 单播:1对1吼

    ​ 广播:多对多吼(会出现广播风暴)

    ​ 不能跨局域网通信。

    -网络层

    ip:定位局域网的位置

    port:唯一标识一台计算机上一个应用程序。

    arp协议:将mac地址获取并解析成ip和port。

    -传输层
    TCP,特点:TCP协议称为流式协议,若想要通信,必须建立连接

    #### 1.1 TCP协议的三次握手:
    

    客户端往服务端发送建立连接请求,服务端回复收到请求同时发送服务端与客户端建立连接的请求,客户端回复收到建立连接的请求,双向通道建立完成。

    #### 12. TCP协议的四次挥手:
    

    服务端向客户端发送断开连接请求,客户端回复收到请求,然后检测自己是否有数据在给客户端发送,如果没有则向客户端发送断开连接请求,客户端回复同意断开连接信息,客户端与服务端断开连接。

    双向通道反馈机制:客户端向服务端发送获取数据请求,客户端发送确认收到的消息,如果服务端没有返回消息,客户端则会继续隔段时间发送一次请求,如果时间过长仍没有收到回复则停止发送请求。

    1.2 UDP协议

    特点:

    • 数据不安全
    • 不需要建立双向通道
    • 客户端发送数据给服务端不需要收到服务端的确认消息
    • 传输速度快
    • 不会有粘包问题

    TCP与UDP的区别:

    TCP:如同是在打电话

    UDP:如同是在发短信

    应用层

    ftp

    http

    http+ssl

    2.socket

    socket用来写套接字客户端与服务端,内部帮我们封装好了7层协议需要做的事情。

    3.手撸socket套接字模板

    3.1 服务端

    import socket

    server = socket.socket()

    server.bind(('127.0.0.1',6666))括号内是ip和端口号,且是元组的形式

    server.listen(6)半连接池

    conn,addr = server.accept()

    data = conn.recv(1024)接收数据的二进制位长度

    conn.send('发送的消息'.decode('utf-8'))

    3.2 客户端

    import socket

    client = socket.socket()

    client.connect(('ip',port))

    client.send()

    client.recv(1024)

    4.subprocess(了解)

    功能:通过代码往cmd创建一个管道,并且发送命令和接收cmd返回的结果。

    用法:

    import subprocess

    obj = subprocess.Ponpen('cmd命令',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)

    success = obj.stdout

    error = obj.stderr.read()

    msg = success + error

    5.粘包问题

    1)不能确定对方发送数据的大小

    2)在短时间内,间隔时间短,并且数据量小的情况下,默认将这些数据打包成一个,多次发送的数据一次性发送。

    6.struct解决粘包问题

    初级版:

    将一个数据的长度打包成一个固定长度的报头,struck.pack('i',len(data))

    对方获取数据时用

    data = struct.unpack('i',headers)[0]

    注意:以什么方式打包必须以什么方式解包

    升级版:

    先将数据存放到字典中,将字典打包发送过去:好处,真实数据长度,文件的描述信息,发送的数据更小。

    dic = {

    'data_len':10000,

    文件的描述信息

    }

    7.上传大文件数据

    客户端

    dic = {

    文件大小

    文件名

    }

    with open(文件名,‘rb')as f:

    for line in f:

    client.send(line)

    服务端

    dic = {

    文件大小

    文件名

    }

    init_recv = 0

    with open(文件名,’wb') as f:

    while init_recv<文件大小:

    data = conn.recv(1024)

    f.write(dara)

    init_recv += len(data)

    8.socketserver(现阶段,了解)

    可支持并发

    import socketserver

    定义类

    TCP:必须继承BaseRequestHandler类

    class MyTcpServer(socketserver.BaseRequestHandler)

    -handle

    内部实现了server = socket.socket()

    server.bind(('127.0.0.1',6666))

    server.listen(5)

    while True:

    conn,addr = server.accept()

    print(addr)

    必须重写父类的handle。当客户端连接时会调用该方法

    def handle(self):

    print(self.client_address)

    while True:

    ​ request.recv(1024)

    ​ self.request.send()

    TCP:

    SOCK_STREAM

    conn.recv

    UDP:

    SOCK_DGRAM

    server.refrom()

    8.1 UDP套接字模板:

    服务端:

    import socket

    server= socket.socket(type=socket_SOCK_DGRAM)

    server.bind((ip,port))

    data,addr = server.refrom(1024)

    客户端

    import socket

    client = socket.socket(type=socket.SOCK_DGRAM)

    ip_port = (ip,port)

    client.sendto(data,ip_port)

    data,_ = client.refrom(1024)

    print(data)

    二、并发编程

    多道技术

    多道:切换+保存状态

    -空间上的复用:支持多个程序使用

    -时间上的复用:遇到IO操作就会切换程序,程序占用CPU时间过长也会被切换。

    1.并发与并行:

    并发:看起来像同时运行:多道技术
    并行:真正意义上的同时运行:多核下
    进程:
    进程是资源单位,每创建一个进程都会生成一个名称空间,占用内存资源。
    程序就是一堆代码
    进程就是一堆代码运行的过程

    2.进程调度:

    时间片轮转法:
    10个进程,将固定时间等分成10等份,分配给每个进程

    分级别反馈队列
    时间短的,执行权限最高放在一级队列,时间长一点的放下面
    1级别:
    2级别:
    3级别:

    3.进程的三个状态:

    就绪态:创建多个进程,排队准备运行
    运行态:进程开始运行,结束、阻塞
    阻塞态:遇到IO操作进入,阻塞态之后进入就绪态
    占用CPU时间过长会进入就绪态

    4.同步与异步:

    同步异步是提交任务的方式,同步指同步提交,是串行的,一个任务结束另一个任务才能提交执行;异步指异步提交,多个任务可以并发运行

    5.阻塞与非阻塞

    阻塞:阻塞态
    非阻塞:就绪态、运行态

    同步和异步,阻塞和非阻塞是不同的概念不能混为一谈。 等待不一定是阻塞,有可能某个任务占用CPU的时间过长, 所以他们不是同一个概念。

    最大化提高CPU的使用率:尽可能减少不必要的IO操作

    6.创建进程的两种方式

      1. p = Process()
         p.start()向操作系统提交创建进程的任务
         p.join()
         p.daemon = True 必须放在start()前面,否则报错
         2. class MyProcess(Process):
              def run(self):
    

    ​ 任务的过程

    ​ p = MyProcess()

    ​ p.daemon = True 必须放在start()前,否则报错

    ​ p.start()

    ​ p.join()

    7.回收进程的两种条件:

    ​ 1.调用join让子进程结束后子进程结束
    ​ 2.主进程正常结束

    8.僵尸进程与孤儿进程

    僵尸进程:凡是子进程结束后pid号还存在的进程
    父进程已经结束

    孤儿进程:主进程已经结束,子进程还在运行

    守护进程:只要主进程结束,所有添加守护进程的子进程都必须结束

    9.互斥锁:

    保证数据安全
    from multiprocessing import Lock
    mutex = Lock()
    mutex = acquire()
    mutex = release()

    10.队列

    from multiprocessing import Queue
    q = Queue(5)
    q.put()
    q.put_nowait()
    q.get()
    q.get_nowait()

    堆栈:LIFO

    10.1 IPC进程间通信

    ​ 进程间的数据是隔离的
    ​ 队列可以让进程间通信
    ​ 把一个程序放入队列中,另一个程序从队列中获取,实现进程间的数据交互。

    10.2 生产者与消费者模型

    生产者:生产数据
    消费者:使用数据

    为了保证平衡:通过队列实现
    生产者将数据扔进队列中,消费者从数据中去数据

    11.线程

    11.1 什么是线程

    ​ 进程是资源单位
    ​ 线程是执行单位

    ​ 创建进程时会自带一个线程(主线程)

    11.2进程与线程的优缺点

    ​ 进程:
    ​ 优点:多核下计算密集型程序
    ​ 缺点:开销资源高于线程

    ​ 线程;优点:占用资源小
    ​ IO密集下,提高效率
    ​ 缺点:无法使用多核优势

    线程间数据是共享的

    12.全局解释器锁

    在CPython中,全局解释器锁(即GIL)是一个互斥锁,可以防止一个进程中的多个线程同时(并行)执行。 锁定是必要的,主要是因为CPython的内存管理不是线程安全的。GIL的存在就是为了保证线程安全

    13.死锁现象

    所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

    14.递归锁

    解决死锁现象
    mutex1,mutex2 = RLock()
    只有这把锁的计数为零才会被下一个人使用

    15.信号量

    ​ 也是一把锁,可以让多个人,多个用户一起使用
    ​ sm = Semaphore(5)

    16.线程队列:保证线程间数据的安全

    import queue
    FIFO:先进先出队列
    queue.Queue()

    ​ LIFO:后进先出队列
    ​ queue.LifoQueue()
    ​ 优先级队列
    ​ queue.PriorityQueue()

    17.event事件

    可以控制线程的执行,让一些线程控制另一些线程的执行

    线程池与进程池
    为了控制进程、线程的创建的数量,保证了硬件能正常运行。

    from concurrent.futures import ProcessPoolExecutor,TreadPoolExecutor

    pool1 = ProssPoolExecutor()默认是CPU的个数

    pool2 = ThreadPoolExecutor()默认是CPU个数*5

    18.回调函数

    pool.submit(函数名,参数).add_done_callback(回调函数名)

    注意:回调函数必须接收一个参数,且这个参数是第一个函数的返回值。

    res1 = res.result() 获取返回值。

    19.协程

    协程:单线程下实现并发,不是任何的单位,是程序员YY出来的名字。

    协程的优点:节省内存资源,进一步提高CPU的利用率(只有在IO密集型程序中才有优点)

    高并发:多进程+多线程+协程

    19.1 协程的手动创建:

    手动实现切换+保存状态:

    yield+next:yield对程序的暂停不会被操作系统识别为IO操作

    19.2 使用gevent实现单线程下的并发

    from gevent import monkey

    monkey,patch_all()监听是否有IO操作

    from gevent import spawn,joinall 实现切换+保存状态

    s1 = spawn(任务1)

    s2 = spawn(任务2)监听是否有IO操作

    joinall([s1,s2])等待所有的程序执行完毕结束,执行下面的程序。

    20.IO模型(了解)

    阻塞IO

    非阻塞IO

    多路复用IO

    异步IO

  • 相关阅读:
    static 关键字
    gitlab 配置到jenkins
    Eclipse下代码字体背景变红/变绿/变黄原因
    构造方法(和python初始化变量类似)
    面向对象(实际就像python跳用自己写的库那样)
    Python 的AES加密与解密
    break 和 continue 的用法
    for循环
    Eclipse快捷键
    java三元运算符
  • 原文地址:https://www.cnblogs.com/ghylpb/p/11739203.html
Copyright © 2011-2022 走看看