网络编程笔记"/>
Python网络编程笔记
三次握手: 在进行面向连接的数据传输前进行传输连接的过程
- 客户端向服务器发送连接请求(问是否可以连接)
- 服务器接收到连接请求进行确认,返回报文
- 客户端收到回复,进行连接建立
四次挥手: 在进行面向连接的数据传输时,断开连接的过程
- 主动方发送报文 告知被动方要断开连接
- 被动方返回报文,告知收到请求,准备断开
- 被动方再次发送报文给主动方,告知准备完毕可以断开
- 主动方发送报文进行断开
tcp
可靠的数据传输
可靠性指数据传输中 无失序 无差错 无丢失 无重复
所有消息传输前一定会建立连接,传输后一定会断开连接
服务端
- 创建套接字
- 绑定地址(IP 端口号)
- 将套接字设置可监听
- 等待接收连接请求
- 收发消息
- 关闭套接字
客户端 - 创建套接字
- 请求连接
- 消息收发
- 关闭套接字
udp
传输特点:
不保证可靠的数据传输
没有连接过程
数据的收发都比较自由,不会受另一端制约
服务端
- 创建套接字 —》 数据报套接字
- 绑定服务端地址
- 消息的收发
4.关闭套接字
客户端 - 创建套接字
- 消息收发
- 关闭套接字
tcp流式套接字 和 udp数据报套接字 区别 - 流式套接字采用字节流的方式传输数据,而数据报套 接字以数据报形式传输
- tcp会产生粘包现象,udp消息是有边界的不会粘包
- tcp传输是建立在连接的基础上,保证传输的可靠性 ,而udp一次接受一个数据报,不保证完整性
- tcp需要依赖listen accept建立连接,udp不用
- tcp 收发消息使用recv send udp用recvfrom sendto
IO input output
凡是在内存中存在数据交换的操作都可以认为是IO操作
比如: 内存和磁盘交互 读写 read write
内存和终端交互 print input
内存和网路交互 recv send
IO密集型程序 : 程序的执行过程中进行大量的IO操作,而只有较少的cpu运算。消耗计算机资源较少,运行时间长。
CPU密集型程序(计算密集型): 程序运行中需要大量的cpu运算,IO操作较少。消耗cpu资源多,运行速度快
IO分类
阻塞IO 非阻塞IO IO多路复用 事件IO 异步IO
阻塞IO : 默认形态 效率很低的一种IO
阻塞情况 : * 因为某种条件没有达到造成的阻塞
e.g. input accept recv
* 处理IO事件的时间消耗较长带来阻塞e.g. 文件的读写过程,网络数据发送 过程
非阻塞IO : 通过修改IO事件的属性,使其变为非阻塞 状态,即避免条件阻塞的情况
- 非阻塞IO往往和循环搭配使用,这样可以不断执行部分需要执行的代码,也不影响对阻塞条件的判断
设置套接字为非阻塞
s.setblocking()
功能 : 设置套接字的阻塞状态
参数 : 设置为False则套接字调用函数为非阻塞
超时检测
将原本阻塞的IO设置一个最长阻塞等待时间,在规定时间内如果达到条件则正常执行,如果时间到仍未达到条件则结束阻塞。
s.settimeout(sec)
功能 : 设置套接字超时时间
参数 : 设置的时间
IO多路复用
定义 : 同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件。 此时形成多个IO时间都可以操作的现象,不必逐个等待执行。
准备就绪 : IO事件即将发生的临界状态
import select
select —》 windows linux unix
poll —》 linux unix
epoll —》 linux unix
r, w, x = select(rlist, wlist, xlist[, timeout])
功能: 监控IO事件,阻塞等待IO事件发生
参数: rlist 列表 存放被动等待处理的IO事件
wlist 列表 存放需要主动处理的IO
xlist 列表 存入如果发生异常需要处理的IO
timeout 超时时间
返回值 : r 列表 rlist中准备就绪的IO
w 列表 wlist中准备就绪的IO
x 列表 xlist中准备就绪的IO
注意事项 :
- IO多路复用 处理IO的过程中不应有死循环出现,使一个客户端长期占有服务端
- IO多路复用是一种并发行为,但是是单进程程序,效率较高
import os
pid = os.fork()
功能 : 创建一个新的进程
参数: 无
返回值: 失败返回一个负数 -1
成功 在原有进程中返回新的进程的PID
在新的进程中返回0
- 子进程会复制父进程全部代码段,包括fork前的代码
- 子进程从fork的下一句开始执行
- 父子进程通常会根据fork返回值的差异选择执行不同 的代码 (使用if结构)
- 父子进程在执行上互不干扰,执行顺序不确定
- 子进程虽然复制父进程内存空间,但是有自己的特性,比如PID号,PCB等
- 父子进程空间独立,各自修改各自的内容,互不影响
multiprocessing 模块创建进程
- 需要将要做的事件封装为函数
- 使用multiprocessing中提供的Process类创建进程对 象
3.通过进程对象和Process 初始化函数 对进程进行设置,并且绑定要执行的事件 - 启动进程,会自动执行相关联函数
- 事件完成后回收进程
创建进程对象
Process()
功能 : 创建进程对象
参数 : name : 给创建的进程起一个名字
默认Process-1
target : 绑定的函数
args : 元组 给target函数按照位置传参
kwargs : 字典 给target函数按照键值出传参
p.start()
功能: 启动进程,此时进程被创建。自动运行进程函数
p.join([timeout])
功能 : 阻塞等待回收响应的进程
参数 : 超时时间
- multiprocessing创建进程是原来进程的子进程,创建后父子进程各自执行互不影响
- 子进程同样是复制父进程的空间,子进程对内容的修改不会影响父进程空间
- join回收子进程,会有效的阻止僵尸进程产生
多进程
优点 : 能并行执行多个任务,提高效率
创建方便,运行独立,不受其他进程影响
数据安全
缺点 : 进程的创建和删除都需要消耗计算机的资源
进程池技术
产生原因 : 如果有大量任务需要多进程完成,且可能需要频繁的创建和删除进程,给计算机带来大量的资源消耗。
原理 : 在进程池内运行一定数量进程,通过这些进程完成进程池队列中的事件,直到事件执行完毕,减少进程不断的创建删除过程。
实施操作方法:
- 创建进程池,在进程池中放入适当进程
- 将事件加入到进程池队列
- 事件不断运行,直到所有事件运行完毕
- 关闭进程池,回收进程
from multiprocessing import Pool
pool = Pool(processes)
功能 : 创建进程池对象
参数 : 表示进程池中有多少进程
pool.apply_async(func,args,kwds)
功能 : 将事件放入进程池队列
参数 : func 要执行的事件
args 给func用元组传参
kwds 给func用字典传参
返回值 : 返回事件对象 通过get()方法获取事件函数返 回值
pool.apply(func,args,kwds)
功能 : 将事件放入进程池队列
参数 : func 要执行的事件
args 给func用元组传参
kwds 给func用字典传参
pool.close()
功能 : 关闭进程池,不能再添加新的事件
pool.join()
功能 : 阻塞等待回收进程池
pool.map(func,iter)
功能 : 将要完成的事件放入进程池
参数 : func 要完成的事件函数
iter 可迭代对象给func传参
返回值 : 事件函数的返回值列表
cookie
fd.send(data)
功能: 向管道写入内容
参数: 要发送的内容
- 几乎可以发送所有python支持的数据
消息队列
队列 : 先进先出
获取文件大小
os.path.getsize(path)
功能 : 获取一个文件的大小
参数 : 文件
进程间通信
进程间由于空间独立,资源无法互相直接获取,此时在不同的进程间进行数据传递就需要专门的通信方法
进程间通信方法(IPC)
管道 消息队列 共享内存 信号 信号量 套接字
管道通信 Pipe
管道 : 在内存中开辟一段空间,形成管道结构,管道对多个进程可见,进程可以对管道进行读写操作
multiprocess —》 Pipe
fd1,fd2 = Pipe(duplex = True)
功能 : 创建一个管道
参数 : 默认为双向管道
如果设置为False 则为单向管道
返回值 :如果双向管道,fd1 fd2都可以进行读写操作
如果是单向管道,则fd1 只可读,fd2只可写
fd.recv()
功能 : 从管道读取内容
返回值 : 读到的内容
- 如果管道无内容则阻塞
在内存中开辟队列结构空间,多个进程可以向队列投放消息,在取出的时候按照存入顺序取出
创建队列
q = Queue(maxsize = 0)
功能 : 创建队列
参数 : maxsize 默认表示根据系统分配空间存储消息
如果传入一个正整数则表示最多存放多少条消息
返回 : 队列对象
q.put(data,[block,timeout])
功能: 存放消息
参数: data 存入的消息 (python数据类型)
block 默认为True表示当队列满的时候阻塞
设置为False则表示非阻塞
timeout 当block为True表示超时时间
data = q.get([block,timeout])
功能 : 取出消息
参数 : block 默认为True 当队列空时阻塞
设置为False表示非阻塞
timeout 当block为True时表示超时时间
返回值 : 返回获取的消息
q.full() 判断队列是否为满
q.empty() 判断队列是否为空
q.qsize() 判断当前队列有多少消息
q.close() 关闭队列
共享内存
在内存中开辟一段空间,存储数据,对多个进程可见。每次写入共享内存中的数据会覆盖之前的内容
from multiprocessing import Value
obj = Value(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype 字符串 要转变的c的数据类型
对比类型对照表
obj 共享内存的初始化数据
返回 : 共享内存对象
obj.value 表示共享内存中的值。对其修改或者使用即 可
obj = Array(ctype,obj)
功能: 开辟共享内存
参数: ctype 要转化的c的类型
obj 要存入共享内存的数据
列表 将列表存入共享内存,数据类型 一致
正整数 表示开辟几个数据空间
管道 消息队列 共享内存
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 操作覆盖内存
双向/单向
效率 一般 一般 较快
应用 多用于两端 使用广泛 复杂,需要 通信 同步互斥机制
线程
什么是线程
线程也是一种多任务编程的方式,可以使用计算机多核资源。线程又被称为轻量级的进程
线程特征
- 线程是计算机核心分配的最小单位
- 一个进程可以包含多个线程
- 线程也是一个运行过程,也要消耗计算机资源。多个 线程共享其进程的资源和空间
- 线程也拥有自己特有的资源属性,比如指令集,TID等
- 线程无论创建还是删除还是运行资源消耗都小于进程
- 多个线程之间并行执行,互不干扰
threading 模块创建线程
threading.Thread()
功能 : 创建线程对象
参数 : name 线程名称
target 线程函数
args 元组 给线程函数传参
kwargs 字典 给线程函数传参
t.start() 启动线程
t.join([timeout]) 回收线程
线程属性
t.is_alive() 查看线程状态
t.name 线程名称 默认Thread-1 。。。。。
t.setName() 设置线程名称
threading.currentThread() 获取当前线程对象
t.daemon
默认情况下,主线的结束不会影响分支线程
如果设置为True 则主线程退出分支线程也会退出
设置方法:
t.daemon = True
t.setDaemon(True)
判断daemon属性:
t.isDaemon()
- 线程daemon属性的设置在start前
- 一般设置daemon后不会在使用join
创建自己的线程类
- 继承Thread类
- 运行Thread类中的__init__方法以获取父类属性
- 重写run方法
进程和线程的区别和联系:
- 两者都是多任务编程的方式,都能够使用计算机多核资源
- 进程创建和删除要比线程消耗更多计算机资源。
- 进程空间独立数据安全性好,有专门的通信方法。
- 线程使用全局变量通信,更加简单,但是往往需要同步互斥操作
- 一个进程可以包含多个线程,线程共享进程资源
- 进程线程都有自己的特有属性资源,如命令、id等
线程通信
通信方法 : 多个线程共用进程空间,所以进程的全局变量对进程内的线程均可见。因此使用全局变量通信是线程主要通信方法。
注意事项 : 线程间通信更容易产生资源争夺,往往需要同步互斥机制保证通信安全
更多推荐
Python网络编程笔记
发布评论