python网络编程到高并发编程(一)

网络编程

1、osi七层协议有
总结为五层:这五层每层都有自己对应的协议越往上越靠近用户、越往下越靠近硬件

(1)应用层
	(1.1)HTTP、FTP、mail协议
(2)传输层(标识应用程序的端口,端口是应用程序与网卡关联的编号)
	(2.1)主要有传输层有四层交换机、四层路由器设备
	(2.2)tcp、udp协议
		(1)tcp协议:
			(1)可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包
		不必再分割。
			(2)数据包包含以太网头、ip头、tcp头、数据
			(3)tcp协议的三次握手、四次挥手
				(1)三次握手步骤
					(1)客户端:SYN-SENT(connect())发送syn(请求) =1 seq(序列号)= x
		(2)udp协议
			(1)不可靠传输即不需要建立握手
			
	(2.3)端口号的范围是0-65535 0-1023为系统占用端口
	
(3)网络层(区分子网)
	(3.1)主要有路由器、三层交换机
	(3.2)IP协议:
		(1)规定网络地址的协议叫ip协议,它定义的地址称之为ip地址(4段10进制)
		(2)子网掩码:表示网络特征的参数(4段10进制)
		(3)通过ip、子网掩码 将二者转换为二进制,通过按位与的方法可以得到 2个ip地址是否处于同一个网段,即是否在同一个局域网、
		(4)ip数据包包含(以太网头、ip头、ip数据)
	(3.3)ARP协议
		(1)局域网通过广播方式通信,如果不在同一个局域网就通过路由方式去分发数据包,网络层引用一套新的地址用来区分不同的区域、子网,该地址就是网络地址
		(2)在同一子网 数据包地址(目标mac、目标IP),不在同子网(网关mac,目标IP)
			(1)网关mac即电脑上显示的DNS服务 端口为53 
			  ps:不在同一网段,访问另外一个网段需要通过源地址先将目标数据包给自身DNS网关,然后自身DNS网关在将该数据包给另外一个DNS网关拿到目标地址的MAC地址

		
(4)数据链路层(找到主机)
	(4.1)主要有网桥、以太网交换机、网卡
	(4.2)以太网协议 ethernet
		(1)以太网协议:一组电信号构成一个包,每个包都由head和data组成
			(1)heaad头 由 发送者(6字节)和接收者地址(6字节)数据类型(6字节)固定18字节
			(2)data包含 最短46字节 最长1500字节超过了分片发送
		(2)mac地址
			(1)head中包含的源和目标地址由来:ethernet规定接入internet的设备都必须具备网卡,发送端和接收端的地址便是指网卡的地址,即mac地址
		(3)广播通信
			(1)有了mac地址 就可以实现在局域网广播通信
			(2)在局域网中的交换机有学习功能,及第一次访问时候交换机会记录下对应端口的源mac地址,然后跟据发送的以太网包里面各个接口捷豹后发现目标地址与自己一样,
			就会返回mac地址,这个时候交换机会记录下交换机该端口的端口号,下次在如果这2个端口在次通信就不需要广播通讯,点对点通讯
(5)物理层
	(5.1)主要有中继器、集线器、双绞线
	(5.2)将数据转化为0101010 二进制

1、什么是套接字:
套接字位于应用层与传输层之间,将传输层以下的协议都封装成了接口
对于应用层来说只需要调用套接字的接口,写出的程序自然是遵循tcp或udp。。。

2、c/s

server必须遵循:
    1、稳定运行,对外一直提供服务
    2、服务必须绑定ip和端口

1、C/S B/S
client----- server
browser-----server

    其中服务端必须具备:
        1、稳定运行,对外一直提供服务
        2、绑定一个固定的ip+port

2、互联网:

    2.1 物理连接介质
    2.2 互联网协议(互联网协议即计算机界的英语)

3、tcp
三次握手

半连接池backlog=5
	限制的同一时刻的请求数而非连接数
四次挥手断开连接
问题:
 1、粘包问题
        tcp协议的的nagle算法会将,数据量较小,并且发送时间间隔较端的多个数据包合并为一个发送

 2、如何解决粘包问题?
     自定义报头

操作系统原理

操作系统(现代操作系统):
        操作系统是位于计算机硬件于软件之间的控制程序
        作用:
            1、将硬件的复杂操作封装成简单的接口,给用户或者应用程序使用
            2、将多个应用程序对硬件的竞争变的有序
1、串行:
    一个任务完完整整地运行完毕后,才能运行下一个任务

2、并发
    看起来多个任务是同时运行的即可,单核也可以实现并发

3、并行:
    真正意义上多个任务的同时运行,只有多核才实现并行


4、cpu的功能:
    cpu是用来做计算,cpu是无法执行IO操作的,一旦遇到io操作,应该让cpu去执行别的任务


5、多道技术
背景:想要再单核下实现并发(单核同一时刻只能执行一个任务)
并发实现的本质就是:切换+保存状态

    1、空间上的复用=》多个进程共用一个内存条,但占用内存是彼此隔离的,而且是物理层面隔离
    2、时间上的复用-》多个进程复用同一个cpu的时间
        cpu遇到IO切换:可以提升效率
        一个进程占用cpu时间过长或者说有另外一个优先级更高的抢走CPU,也会切走:为了实现并发效果不得已而为之,反而会降低程序的执行效率


6、我们写的携程尽量减少io操作

什么是进程

什么是进程
    进程指的就是一个正在运行的程序,或者说是程序的运行过程,即进程是一个抽象的概念
    进程是起源于操作系统的,是操作系统最核心的概念,操作系统所有其他的概念都是围绕进程展开的
    
为何用进程
    实现并发

1、开启进程的两种方式:
        #方式一:
        from multiprocessing import Process

        def task(x):
            pass

        def func():
            pass

        if __name__ == "__main__":
            p=Process(target=task,args=(1,))
            p.start() # 仅仅只是向操作系统发送一个开启进程的信号

            func()

        #方式二:
        from multiprocessing import Process

        class Process:
            def start(self):
                self.run() #p.run()

        class Myprocess(Process):
            def run(self):
                pass

        if __name__ == "__main__":
            p=Myprocess()
            p.start() # 仅仅只是向操作系统发送一个开启进程的信号

            func()

    2、进程之间内存空间彼此隔离

    3、p.join():让p的父进程等待p执行完毕,并且回收子进程(僵尸进程)占用的pid

    4、pid:进程id号,即进程在操作系统内的身份证号
        ppid:当前进程父进程的id号
1、守护进程
        守护进程本质就是一个“子进程”,该“子进程”在父进程代码
        运行完毕后就自动销毁

        什么时候需要开启子进程?
            当父进程中需要将一个任务并发执行时,可以开启子进程

        什么时候需要将子进程设置为守护进程?
            当父进程代码运行完毕后,子进程没有存在的意义了,就应该
            将该子进程设置为守护进程

    2、互斥锁,信号量
        将多个并发的任务对修改共享数据的操作变成串行
        牺牲了效率,但保证数据安全

        互斥锁vs p.join()
            1、互斥锁是局部串行
            2、p.join()所有代码整体都是串行的

		信号量就好比共享锁

    3、IPC机制(*****)
        1、PIPE
        2、队列:PIPE+锁
        q=Queue()
        q.put()
        q.get()
    4、生产者消费者模型(******)
        该模型中包含两大重要的角色:
            1、生产者:代表产生数据的任务
            2、消费者:代表处理数据的任务

        实现:
           生产者---》队列《----消费者

        该模型的优点:
            1、实现了生产者与消费者的解耦和
            2、平衡了生产者的生产力与消费者的消费力

        什么时候用?
            程序中存在明确的两类任务,一类负责造数据,另外义类负责处理数据

什么是线程

01 什么是线程
    进程其实不是一个执行单位,进程是一个资源单位
    每个进程内自带一个线程,线程才是cpu上的执行单位

    如果把操作系统比喻为一座工厂
        在工厂内每造出一个车间===》启动一个进程
        每个车间内至少有一条流水线===》每个进程内至少有一个线程

    线程=》单指代码的执行过程
    进程-》资源的申请与销毁的过程

02 进程vs线程
    1、 内存共享or隔离
        多个进程内存空间彼此隔离
        同一进程下的多个线程共享该进程内的数据

    2、创建速度
        造线程的速度要远远快于造进程

GIL

1、GIL全局解释器锁
        什么是?
            GIL本质就是一个把互斥锁,是将多个并发的线程对共享数据的修改
            变成“串行”

        为何有?
           Cpython解释器的垃圾回收机制不是线程安全的


        如何用?
            有GIL的存在,导致同一个进程内的多个线程同一时刻只能有一个运行
            即同一进程的多个线程无法实现并行=》无法利用多核优势
            但是可以实现并发的效果

        什么是多核优势?
            多核即多个cpu,多个cpu带来的优势是计算性能的提升,所以

            IO密集型:
                多线程
            计算密集型
                多进程

        GIL vs 自定义互斥锁
            GIL相当于执行权限,意思是在一个进程内的多个线程想要执行,必须
            先抢GIL,这把锁的特点是,当一个线程被剥夺走cpu的执行权限的同时会被
            解释器强行释放GIL

进程池与线程池

进程池与线程池
        什么是?
            池:池用来限制进程/线程个数的一种机制
        为何用?
            当并发的任务数远大于计算机的承受能力,应该用池的概念
            将并发的进程数/线程数控制在计算机能承受的数目

        如何用?
            from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
            def task(n):
                return n**2
            def func(future):
                print(future.result())

            if __name__ == '__main__':
                p=ProcessPoolExecutor(4)
                p.submit(task,10).add_done_callback(func)

                p.shutdown(wait=True)
                # pool.close()
                # pool.join()
                print('主')

        提交任务的两种方式:
            1、同步:提交完任务后就在原地等待,直到任务运行完毕并且拿到返回值后,才运行下一行代码
            2、异步:提交完任务(绑定一个回调函数)后不原地等待,直接运行下一行代码,等到任务运行有返回值自动触发回调的函数的运行

        程序的运行状态(阻塞,非阻塞)
            1、阻塞:
                IO阻塞
            2、非阻塞:
                运行
                就绪

协程

1、协程
        什么是?
            协程指的是单线程下由应用程序级别实现的并发
            即把本来由操作系统控制的切换+保存状态,在应用
            程序里实现了

            协程的切换vs操作系统的切换
            优点:
                切换速度远快于操作系统
            缺点:
                一个任务阻塞了,其余的任务都无法执行

            ps:只有遇到io才切换到其他任务的协程才能提升
                单线程的执行效率

        为何用?
            把单个线程的io降到最低,最大限度地提升单个线程的执行效率

        如何实现?
            from gevent import spawn,monkey;monkey.patch_all()
            
io模型
        block io
        nonblocking io
            1、对cpu的无效占用率过高
            2、不能即时反馈客户端的信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值