• day30 网络编程 之进程,线程,协程


    进程点进去

    线程点进去

    协程点进去

    什么是进程
      进程(有时称为重量级进程)是一个执行中的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。同一个程序执行两次,属于是两个不同进程。
    什么是线程 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。与同属一个进程的其它线程共享进程所拥有的全部资源。
      一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。 就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机; 运行状态是指线程占有处理机正在运行; 阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。
    什么是协程? 协程是“微线程”,并非实际存在;是由程序员人为创造出来并控制程序:先执行某段代码、再跳到某处执行某段代码。   如果遇到非IO请求来回切换:性能更低。   如果遇到IO(耗时)请求来回切换:性能高、实现并发(本质上利用IO等待的过程,再去干一些其他的事)

     GIL

    GIL
    果多个线程执行同一个功能,那么执行流程是多个线程先访问到解释器的代码拿到执行权限,然后将target指向的的代码交给解释器的代码去执行。
    解释器的代码是所有线程共享的,所以垃圾回收线程也可能访问到解释器的代码而去执行自己的职能,这就导致了同一个共享数据同时被使用和回收,使用和回收是矛盾的。
    解决这种问题就是加锁处理保证python解释器同一时间只能执行一个任务的代码。GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理。

    这两天的内容具体功能和作用如下:(个人理解)

    # 我们昨天发送的数据都是很小的数据,但是在生活中我们接触的数据不能都是这么小的数据,会有很大的数据,
    # 那么我们就需要有更加规范的操作,不然就会很混乱,就相当于你写一篇几万字的文章然后没有标点符号一样,
    # 别人无法顺利准确地理解你写出的意思,会有误解出现,我们为了避免误解,就需要把标点符号添加上,
    # 那么就会有一系列的规矩去约束我们的操作,这一切的约束都是为了让我们的数据传输更加的顺畅,更加的具有逻辑性
    # 更有条理,更便于互相理解,我传输过去我理解,同时要考虑到你接收你理解,然后还有通过计算机操作的时候
    # 计算机也理解,三方都更顺畅的沟通,所以我们会有报头的概念(就是为了避免数据过大然后产生连粘,
    # 它会让我们的数据有更清晰的断点,它里面会包含一些描述性信息,这样就相当于每次传输都会有一个主标题为了
    # 更加清晰地表述出数据的内容梗概,它会有固定的长度,为了规范,然后把固定的长度转为字符串再转为字节为了便于
    # 传输,只有字节可以传输,报头后面就连接具体的传输内容,同理传输的内容也需要转为字符串然后再转为字节),
    # 会需要subprocess,会有json,会需要strcut,
    # 都是为了规范操作,这些规矩我们要把它学会,然后理解,运用就可以顺利地跟其他计算机交互。

     回顾:

    1、网络=物理连接介质+互联网协议
    2、OSI七层:应,表,会,传(tcp/udp),网(ip),数(ethernet),物
    3、tcp三次握手建立连接,四次挥手断开连接
        connet()--------->accept()
    
    4、ip+port:标识全世界范围内独一无二的一个应用程序
        server.bind((ip,port))
    
    5、C/S
        Client:ip+port会随意变
        Server:
            一定要绑定ip+port
            应该支持并发连接
            服务端一旦开启一直运行到世界末日
    
    
    今日内容:
        坑:recv(1024)
    
        粘包问题:自定义应用层协议
        TCP:流式协议
    View Code

    subprocess模块:

    这个模块的作用就是跟系统操作相关的调用系统命令,类似于os模块,比os更加强大。
    它本身自带一个管道,这个管道就类似于临时存储数据的的容器,把中间值存入里面,

    然后当需要的时候就从中取出。取出的时候里面有多少就可以取出多少,同一份内容不会重复取出,
    意思就是只有一份内容,你反复执行取出操做,它只能给你倒出一次,倒完了就没有了。

    然后管道里面的执行命令分为错误命令和正确命令,分别存储,用不同的关键字操作。

    import subprocess
    
    obj=subprocess.Popen('dir',shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
    # print('========hahahahahah')
    
    # print(obj.stdout.read().decode('gbk'))
    # print(obj.stdout.read().decode('gbk'))
    # print(obj.stdout.read().decode('gbk'))
    # print(obj.stdout.read().decode('gbk'))
    # print(obj.stdout.read().decode('gbk'))
    
    print(obj.stderr.read().decode("gbk"))
    View Code

    跟subprocess模块相关操作:

    服务端

    import subprocess
    from socket import *
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8081))
    # print(server)
    server.listen(5)
    while True:
        conn,addr=server.accept()
        # print(conn)
        print(addr)
        while True:
            try:
                cmd=conn.recv(8096)
                if not cmd:break #针对linux
    
                #执行命令
                cmd=cmd.decode('utf-8')
                #调用模块,执行命令,并且收集命令的执行结果,而不是打印
                obj = subprocess.Popen(cmd, shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                stdout=obj.stdout.read()
                stderr=obj.stderr.read()
                #发送命令的结果
                conn.send(stdout+stderr)
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    View Code

    同上,客户端:

    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8081))
    
    while True:
        cmd=input('>>: ').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
    
        data=client.recv(1024)
        print(data.decode('gbk'))
    
    client.close()
    View Code

    粘包现象:

    服务端:
    import time
    from socket import *
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8082))
    
    server.listen(5)
    
    conn,addr=server.accept()
    
    # res1=conn.recv(1)
    # print(res1)
    # res2=conn.recv(1)
    # res3=conn.recv(1)
    # res4=conn.recv(1)
    # res5=conn.recv(1)
    # print(res2)
    # print(res3)
    # print(res4)
    # print(res5)
    
    
    
    # res1=conn.recv(1)
    # print(res1)
    # time.sleep(4)
    # res2=conn.recv(1024)
    # print(res2)
    
    
    print(conn.recv(1111111111111111111111111111111111111111111))
    print(conn.recv(5))
    
    
    
    
    #===============================================
    客户端
    import time
    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8082))
    
    client.send(b'hello')
    # time.sleep(3)
    client.send(b'world')
    View Code

    struct模块:

    它就是把数字转成固定长度的bytes类型。

    struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #这个是范围

    import struct
    
    #帮我们把数字转成固定长度的bytes类型
    res=struct.pack('i',123123)
    print(res,len(res))
    
    res1=struct.unpack('i',res)
    print(res1[0])
    
    
    
    # 有兴趣可以把上图里的都试一遍,这里只是试了一种方法,i
    View Code
    服务端
    import subprocess
    import struct
    from socket import *
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8084))
    # print(server)
    server.listen(5)
    while True:
        conn,addr=server.accept()
        # print(conn)
        print(addr)
        while True:
            try:
                cmd=conn.recv(8096)
                if not cmd:break #针对linux
    
                #执行命令
                cmd=cmd.decode('utf-8')
                #调用模块,执行命令,并且收集命令的执行结果,而不是打印
                obj = subprocess.Popen(cmd, shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                stdout=obj.stdout.read()
                stderr=obj.stderr.read()
                #第一步:制作报头:
                total_size=len(stdout)+len(stderr)
    
                header=struct.pack('i',total_size)  # 这里是打成一个包,包里面是一个数字的固定长度
                #第二步:先发报头(固定长度)
                conn.send(header)
    
                #第三步:发送命令的结果
                conn.send(stdout)
                conn.send(stderr)
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    View Code
    客户端
    import struct
    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8084))
    
    while True:
        cmd=input('>>: ').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
    
        #第一步:收到报头
        header=client.recv(4)
        total_size=struct.unpack('i',header)[0]  # 这里是把接收到的数据解包,得到它原本的样子,(类似于压缩解压缩)
    
        #第二步:收完整真实的数据
        recv_size=0
        res=b''
        while recv_size < total_size:
            recv_data=client.recv(1024)
            res+=recv_data
            recv_size+=len(recv_data)
        print(res.decode('gbk'))
    
    client.close()
    View Code

    解决粘包问题:终结篇

    import struct
    
    #帮我们把数字转成固定长度的bytes类型
    # res=struct.pack('i',123123)
    # print(res,len(res))
    #
    # res1=struct.unpack('i',res)
    # print(res1[0])
    
    
    # res=struct.pack('q',121231231233123)
    # print(res,len(res))
    
    
    
    import json
    header_dic={
        'md5':'asdfasdfasdfasdfasdfasdf',
        'total_size':1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111,
        'filename':'a.txt'
     }
    
    header_json=json.dumps(header_dic)
    
    header_bytes=header_json.encode('utf-8')
    print(len(header_bytes))
    header_size=struct.pack('i',len(header_bytes))
    
    
    # conn.send(header_size) ##recv(4)
    # conn.send(header_bytes)  #recv(报头长度)
    # conn.send(stdout)
    # conn.send(stderr)
    View Code
    服务端:
    import subprocess
    import struct
    import json
    from socket import *
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8086))
    # print(server)
    server.listen(5)
    while True:
        conn,addr=server.accept()
        # print(conn)
        print(addr)
        while True:
            try:
                cmd=conn.recv(8096)
                if not cmd:break #针对linux
    
                #执行命令
                cmd=cmd.decode('utf-8')
                #调用模块,执行命令,并且收集命令的执行结果,而不是打印
                obj = subprocess.Popen(cmd, shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                stdout=obj.stdout.read()
                stderr=obj.stderr.read()
    
    
                # 1:先制作报头,报头里放:数据大小, md5, 文件
                header_dic = {
                    'total_size':len(stdout)+len(stderr),
                    'md5': 'xxxxxxxxxxxxxxxxxxx',
                    'filename': 'xxxxx',
                    'xxxxx':'123123'
                }
                header_json = json.dumps(header_dic)
                header_bytes = header_json.encode('utf-8')
                header_size = struct.pack('i', len(header_bytes))
    
                # 2: 先发报头的长度
                conn.send(header_size)
    
                # 3:先发报头
                conn.send(header_bytes)
    
                # 4:再发送真实数据
                conn.send(stdout)
                conn.send(stderr)
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    View Code
    客户端:
    import struct
    import json
    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8086))
    
    while True:
        cmd=input('>>: ').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
    
        # 1:先收报头长度
        obj = client.recv(4)
        header_size = struct.unpack('i', obj)[0]
    
        # 2:先收报头,解出报头内容
        header_bytes = client.recv(header_size)
        header_json = header_bytes.decode('utf-8')
        header_dic = json.loads(header_json)
    
        print(header_dic)
        total_size = header_dic['total_size']
    
        # 3:循环收完整数据
        recv_size=0
        res=b''
        while recv_size < total_size:
            recv_data=client.recv(1024)
            res+=recv_data
            recv_size+=len(recv_data)
        print(res.decode('gbk'))
    
    client.close()
    View Code

    使用文件操作写入一个视频,图片,文件:

    应该还有写入一首歌的操作,一样的模式,以后可以试试

    # with open(r'G:python基础课程笔记以及视频day29part1.avi', 'rb')as 
    #         read_f, open(r'G:python基础课程笔记以及视频day29part2.avi', 'wb')as write_f:
    #     for line in read_f:
    #         write_f.write(line)
    # with open(r'G:每日课程截图day99.png', 'rb')as read_obj,
    #     open(r'G:每日课程截图day990.png', 'wb')as write_obj:
    #     for line in read_obj:
    #         write_obj.write(line)
    # 就像上面写入一个视频和一个图片一样重新写入一个文件,操作方式完全无差别,唯一需要改变的就是编码的问题,
    # 文件不一定是使用二进制编码的,所以不能够使用rb,wb,要使用r,w,然后需要转编码。这样就可以了,比使用u盘传输快多了。
    
    with open(r'D:pythonday29dir.py', 'r', encoding='utf-8')as re_obj, 
            open(r'D:pythonday29dir1.py', 'w', encoding='utf-8')as wr_obj:
        for line in re_obj:
            wr_obj.write(line)
    # print(line)
    View Code
  • 相关阅读:
    ios每日一发--Leanclude数据云存储以及登录 注册账户
    ios每日一发--仿侧边抽屉效果
    ios-自定义alertView提示框
    ios
    UIStepper 缩放:UI的使用
    UIButton 关灯小实验
    将一个字典内的内value转换为集合:返回一个数组,此数组中包含输入字典的键值对中的数组的所有元素(为NSArray添加category)
    为集合排序的三个方法
    NSMutableDictionary
    头文件导入方式
  • 原文地址:https://www.cnblogs.com/2012-dream/p/7911314.html
Copyright © 2020-2023  润新知