网络编程+并发编程总结

网络编程+并发编程

架构:B/S 和 C/S
	C/S:充分发挥PC机的性能
	B/S:统一了应用的接口,隶属于CS架构
	
	
OSI模型  七层:表示层,会话层,应用层,传输层,网络层,数据链路层,物理层。
咱们用五层

应用层	http协议   https协议   ftp协议  snmp/pop3/stmp/dns
传输层	tcp udp 协议	(四层交换机)
网络层	IP协议/icmp协议	路由器	(三层交换机)
数据链路层	arp协议,交换机  (二层交换机)
物理层	网卡,双绞线     (传输电信号)
arp/rarp
  Arp协议(地址解析协议):经过目标ip地址获取目标mac地址    arp涉及到的物理设备:二层交换机  rarp:经过mac地址找ip地址
物理地址:mac地址全球惟一,每一个电脑的网卡上
Ip地址:  四位点分十进制			三十二位点分二进制ipv4/ipv6  : 4位点分十进制,6为冒分16进制

交换机的通讯方式:
	单播:点对点
	组播:点对多
	广播:向多个pc端发送数据包

交换机和路由器的区别?
交换机是组织局域网的,通过内部处理解析数据,将数据已点对点,点对多的方式发送给目标
路由器是跨网段的数据传输,路由出网络传输的最佳路径



 socket 介于应用层和传输层的socket抽象层


Tcp:  可靠、面向链接的双全工通讯 无边界的字节流 慢 占用系统中的链接资源  1 全双工的  面向字节流的(无边界的字节流,多条tcp数据之间没有边界)  2 可靠,不是不安全,更多的是保证数据的网址性  3 (面相连接,必需要先创建链接再进行同窗)三次握手,四次挥手   4 慢:通讯  创建/断开链接 保证数据的完整性的机制  5 占用系统资源(核心要解决的问题)    在不使用任何异步机制(进程/线程/协程),在阻塞io模型中,一个server端只能和一个client端相连    conn1,conn2,conn3    sk = socket.socket()    sk.setblocking(False) # 异步的概念    conn_lst = []    try:      conn,addr = sk.accept()      conn_lst.append(conn)    except BlockingIOError:      for conn in conn_lst:        try:          conn1.recv()  # 有数据在缓存里面就接收,没有数据就报错        except BlockingIOError:pass
Udp:  无链接的,面向数据报,面向数据报的,不可靠,速度快,能传输的数据长度有限。能够同时和多个客户端通讯  不会粘包、速度快、能够和任意多个客户端进行互相通讯  容易丢失数据、传输的数据长度有限
  
三次握手:(必须是客户点先发起)
1.客户端发起SYN请求连接服务端          
2.服务端收到请求,向客户端发送能够链接的请求     ACK
3.客服端收到链接,链接成功            ACK


四次挥手:(客户端和服务端均可以发起)

1.客户端发起断开链接的FIN请求
2.服务端收到请求,而后准备断开链接的一些事物
3.服务端发送请求,我已经准备完毕,能够断开了
4.客户端收到请求,断开链接。
为何挥手是四次?   当我仍然有数据发送的时候,还能够发送!
为何会发生黏包:由于有缓存机制,连续发或者连续收。(在数据传输过程当中,接收数据端接收数据时不知道该如何接收,形成的数据混乱现象)
合包机制:nagle算法 — 发数据的时候一点一点发,可是接收的时候会一次收到。 
拆包机制:发送的数据太大,分开发送,接收的时候,最后不能刚刚接完,就会发生黏包。
都是发生在发送端。 全部的数据都会在接收端的缓存区中被合在一块儿,若是没有及时获取信息,那么消息会粘在一块儿。
发生在接收端
如何解决黏包?

自定义表头:用struct模块,事先将要发送文件的大小存下来,发送 过去,而后按着指定数据开始接收。
Struct 模块  能够将一个整数,封装为一个指定(通常为4)字节数的数字,这样接收端就能够指定大小接收这个数字。

各类网络设备  传输层    四次防火墙/四层防火墙/四层交换机  网络层    路由器  防火墙 三层交换机  数据链路层  交换机 网卡  物理层    网线
socketserver(threading/socket/selector)  帮助你完成server端的并发效果模块socket在应用层和传输层之间,socket是一组封装了后四层协议数据拼接的接口。

操做系统

Dos系统			#单用户单任务
Windows系统		#单用户多任务(早起的Windows)
Unix系统			#多用户多任务

操做系统的做用:1)封装接口,让用户方便使用 	2)对系统资源的分配与调度

计算机的五大组成部分:运算器。控制器。存储器。输入设备。输出设备。

编程语言发展史:机器语言,汇编语言,高级语言

并行:(两件事或者多件事)同一时间点,同时执行 (多个CPU)
并发:(两件事或者多件事)同一时间间隔,交替执行
阻塞:程序由于相似IO等待、等待时间等致使没法继续执行
非阻塞:程序遇到相似于IO操做时,再也不阻塞等待,若是没有及时的处理IO,就会报错或者跳过等待其余操做,
同步:某一个任务的执行必须依赖另外一个任务的返回结果  -任务(当前所在的代码和另外一个独立的任务)
异步:一个任务的执行,不须要依赖另外一个任务的返回,只须要告诉另外一个任务一声
### p.start() 只是向操做系统发了一个启动的命令,至于操做系统何时启动我无论,这就是一个典型的异步非阻塞
进程:cpu资源分配的最小单位    	进程由三部分组成:代码段,数据段,PCB(进程控制块)  资源独立,能利用多核,占用操做系统的资源大,有数据安全问题
线程:cpu资源调度的最小单位		线程由三部分组成:代码段,数据段,TCB(线程控制块)
  资源共享,能利用多核,占用操做系统的资源相对少,有数据安全问题  协程:操做系统不可见  资源共享,不能利用多核,本质是一条线程,占用操做系统的资源就 至关于一条线程,不存在数据安全问题进程:  资源独立线程  处理并发   (同时处理多个任务)GIL锁 CPython解释器中管理线程的机制  保证多个线程,只有一个线程在同一时间点能访问cpu  CPython解释器致使了咱们不能充分利用多线程来访问多个cpu  多进程:帮助咱们Cpython解释器下利用多核协程  在单线程中,有n个任务,这n个任务若是是同步执行,那么全部的io时间是累加在一块儿的        若是这n个任务可以共享全部的io时间  完成一个任务,遇到io以后可以切换到另外一个任务执行,全部的io操做的时间还能作其余任务的执行    这样就能经过一条线程完成多个任务。    协程:切换也是有开销的,切换的开销就和函数调用的开销是同样的。      asyncio    内置的异步模块 (进程、线程、协程)    gevent     扩展的协程模块    aiohttp   扩展模块  帮助咱们利用协程完成http请求的模块数据安全  多个进程操做一个文件,加锁  多个线程操做一个全局变量,加锁    若是是+=   *=  /=  -=  都存在数据不安全的问题    append remove  pop extend 不存在数据不安全的问题  协程 永远不会数据不安全,由于协程是由程序员控制的,而程序员控制的只能是代码,而不是CPU指令      import dis      dis.dis()  # 查看CPU指令  
进程的三大基本状态:
	就绪状态:已经得到运行所需的全部资源,除CPU
	执行状态:已经得到全部资源包括CPU,处于正在运行
	阻塞状态:由于各类缘由,进程放弃了CPU,致使进程没法继续执行,此时进程处于内存中,继续等待获取CPU的一种状态。ß

进程学的东西: multiprocessing

1)Process模块
	线程的建立 	
	1)直接建立
	p = Process(target = func, args = (元组形式, 为func所传的参数)) #实例化进程对象	
	2)继承 (Process)

	多线程的开启	1)for循环		2)多个对象实例化
	方法:
		start()		#开启进程
		join()			#感知进程的结束,异步变同步
		is_alive()		#判断进程是否存活
		terminate()	#杀死一个进程
	属性:
		name			#获取进程名
		pid				#获取进程号
		daemon = True 	#守护进程    
		守护进程的特色:
			#当主进程代码结束后,守护进程随主进程结束
			#守护进程不能再建立子进程
			#守护进程必须在start以前			

2)	锁  		Lock模块			(互斥锁/同步锁)  只能acquire一次
		lock = Lock()	#实例化一个锁对象
		lock.acquire()	#上锁
		lock.release()	#解锁
			RLock模块		(递归锁)
		递归锁能够同时acquire屡次,可是必须acquire几回就必须release几回。都在就会陷入死锁状态
			死锁
		典型的例子:科学家吃面    (一我的拿着面,一我的拿着叉子,到最后谁也吃不上面)

	信号量	Semaphore模块
		sem = Semaphore(int数据类型)	#能够指定有多少线程能够同时拿到锁
		sem.acquire()					#须要上锁将这些数据锁住
		sem.release()
	事件		Event模块
		e = Event()
		e.wait()	#根据is_set()的状态来决定,自身的阻塞状态  若是is_set()为False则为阻塞,若是is_set()为True则为非阻塞
		e.is_set()		#默认为False,
		e.set()		#将is_set()的状态变为True
		e.clear()		#将is_set()的状态变为False

	典型例子:红绿灯事件	

3)进程间通讯(IPC)
	Queue模块		#队列     先进先出    First in first out
		q = Queue()	#建立队列对象(能够指定大小)
		q.put() 		#向队列中添加元素(若是队列以满处于阻塞状态,只有当队列不满才能够继续添加)
		q.get()		#取出队列中元素(若是队列中元素为空处于阻塞状态,只有对列中有元素才能够继续取出)
		q.full()		#判断一个对列是否 已满
		q.empty()		#判断一个对列是否为空
		q.put_nowait()	 #不阻塞,若是能够继续往队列中放数据就继续放,不能放就报错
		q.get_nowait()	 #不阻塞,若是有数据就直接获取,没有数据就报错
	JoinableQueue()模块
		q = JoinableQueue()
						#继承了Queue模块,可是新增了两个方法
		q.task_done()   	#统计对列q有多少个元素被拿走(拿走一个数据就给join返回一个结果),一般与q.get()在一块儿用  用于生产者
		q.join()			#感知一个对列的数据被所有执行完毕  与q.put()在一块儿用      用于消费着
	
	队列  =  管道  +  锁
		
	重点:生产者消费着模型  应用场景:爬虫/高并发的web程序server
		
	Pipe模块			#管道   (自己是不安全的)         (双全工)
		p = Pipe()
		conn1, conn2  = Pipe()
	
		管道是不安全的
		管道是用于多进程之间通讯的一种方式
		若是在单进程中使用管道,那么就是conn1收数据,conn2发数据
							若是是conn1发数据,那么conn2收数据
		若是在多进程中使用管道,那么就必须是父进程中用con1收,子进程中使用conn2发
									父进程使用conn1发,子进程中使用conn2收
									父进程使用conn2收,子进程中使用conn1发
									父进程使用conn2发,子进程中使用conn1收
		在管道中有一个著名的错误叫作EOFERrror。
		是指:父进程中若是关闭了发送端,子进程还继续接受数据,那么就会引起EOFError

4)数据共享	Manager模块    Value模块
	men = Manager()
	(1)
	m.list(列表数据)
	m.dict(字典数据)
	(2)
	with Manager() as m:
		……

5)进程池		Pool模块

	p = Pool(os.cup_count() +1)		#开启多进程以后,每次处理数据只能指定个数个处理
	
	p.close()
	p.join()	#close在join以前

	方法:
		map(func, itreable)	#异步处理 itreable ,有返回值,返回值是,每个func的返回值组成的列表, 自带close和join
		apply(func, args)	#同步处理		有返回值,返回值为func的返回值   不须要加close和join
		apply_async(func, args, callback)	#异步处理,有返回值,返回一个对象,这个对象有get方法,能够获取func的返回值
									#这个get只能一个一个获取,以咱们通常处理完全部线程后再获取数据
									#func的返回值能够做为参数传给callback这个回调函数。回调函数在主进程中执行
		apply函数中的全部进程都为普通进程
		apply_async函数中的全部进程都为守护进程




线程学的东西:threading

GIL:全局解释器锁(只有CPython才有)
	锁的是线程:同一时间只容许一个线程访问CPU      #(没有真正的并行)

1)Thread模块

	线程的建立
	1)t = Thresd(target= func. args = (元组,为func所传的参数))   实例化线程对象
	2)继承
	
	多线程的建立
	1)for 循环
	2)直接实例化多个对象

2)	锁
		Lock		#互斥锁(同步锁)
		RLock 	#递归锁
		死锁		#死锁
	 
	信号量	Semaphore模块
		sem = Semaphore(int数据类型)	#能够指定有多少线程能够同时拿到锁
		sem.acquire()					#须要上锁将这些数据锁住
		sem.release()

	事件		Event模块
		e = Event()
		e.wait()	#根据is_set()的状态来决定,自身的阻塞状态  若是is_set()为False则为阻塞,若是is_set()为True则为非阻塞
		e.is_set()		#默认为False,
		e.set()		#将is_set()的状态变为True
		e.clear()		#将is_set()的状态变为False

3)条件	Condition模块
	
		条件是让程序员自行去调度线程的一个机制
		
		方法:
		acquire()
		release()
		wait()   #让线程阻塞住
		notify(int数据类型)	#是指给wait发一个信号,让wait变成不阻塞						#int数据类型,是指你要给多少wai发信号
	

4)定时器		Timer模块

		建立:Timer(time, func)
				#time:睡眠时间,以秒为单位
				#func:睡眠以后,须要执行的任务
		

5)线程池


进程与线程的区别:
	进程资源分配的基本单位,线程是cpu调度的基本单位。
	线程不能够本身独立拥有资源。线程的执行,必须依赖于所属进程中的资源。
	进程中必须至少应该有一个线程。

线程和进程的比较:
	1)cpu切换进程比切换线程慢不少,在python中若是IO操做过多的话,使用线程最好
	2)在同一个进程内,全部线程共享这个进程pid,也就是说全部线程共享所属进程的全部资源和内存地址
	3)在同一个进程内,全部线程共享该进程中的全局变量
	4)由于GIL锁的存在,在CPython中,没有真正的线程并行。可是有真正的多进程并行
		当你的任务是计算密集的状况下,使用多进程好。
		总结:在CPython中,IO密集用多线程,计算密集用多线程。
	5)关于守护线程和守护进程的事情:(注意:代码执行结束,并不表明程序结束)
		守护进程:要么本身正常结束,要么根据父进程的代码执行结束而结束
		守护线程:要么本身正常结束,要么根据父线程的执行结束而结束(会等其他子线程运行结束)
相关文章
相关标签/搜索