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:流式协议
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"))
跟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()
同上,客户端:
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()
粘包现象:
服务端:
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')
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
服务端
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()
客户端
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()
解决粘包问题:终结篇
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)
服务端:
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':''
}
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()
客户端:
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()
使用文件操作写入一个视频,图片,文件:
应该还有写入一首歌的操作,一样的模式,以后可以试试
# with open(r'G:\python基础课程笔记以及视频\day29\part1.avi', 'rb')as \
# read_f, open(r'G:\python基础课程笔记以及视频\day29\part2.avi', 'wb')as write_f:
# for line in read_f:
# write_f.write(line)
# with open(r'G:\每日课程截图\day9\9.png', 'rb')as read_obj,\
# open(r'G:\每日课程截图\day9\90.png', 'wb')as write_obj:
# for line in read_obj:
# write_obj.write(line)
# 就像上面写入一个视频和一个图片一样重新写入一个文件,操作方式完全无差别,唯一需要改变的就是编码的问题,
# 文件不一定是使用二进制编码的,所以不能够使用rb,wb,要使用r,w,然后需要转编码。这样就可以了,比使用u盘传输快多了。 with open(r'D:\python\day29\dir.py', 'r', encoding='utf-8')as re_obj, \
open(r'D:\python\day29\dir1.py', 'w', encoding='utf-8')as wr_obj:
for line in re_obj:
wr_obj.write(line)
# print(line)
day30 网络编程 之进程,线程,协程的更多相关文章
- Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程
1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...
- 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型
本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...
- 进程&线程&协程
进程 一.基本概念 进程是系统资源分配的最小单位, 程序隔离的边界系统由一个个进程(程序)组成.一般情况下,包括文本区域(text region).数据区域(data region)和堆栈(stac ...
- Python 进程线程协程 GIL 闭包 与高阶函数(五)
Python 进程线程协程 GIL 闭包 与高阶函数(五) 1 GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的 ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- python的进程/线程/协程
1.python的多线程 多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有 ...
- python-socket和进程线程协程(代码展示)
socket # 一.socket # TCP服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bin ...
- python基础(16)-进程&线程&协程
进程之multiprocessing模块 Process(进程) Process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建. 介绍 初始化参数 Process([group [, t ...
- python 进程 线程 协程
并发与并行:并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔内发生.在单核CPU下的多线程其实都只是并发,不是并行. 进程是系统资源分配的最小单位,进程的出现是为了更好的 ...
随机推荐
- select前台转义后台取到的值为对应的文本 select同时接受list和map
简单描述:select动态取值 要求是根据后台传过来的值在前台进行转义,emmm干就完了 思路分析:后台同时传过去一个map一个list ,map用来前台转义,list用来获取值,list取到的值相当 ...
- 动态获取后台传过来的值作为select选项
问题描述:点击左侧菜单项,进入对应的具体页面a.html,页面上方有个select框,点击框后,会浮现选择项. 解决思路:对左侧菜单项添加一个onclick事件,进入后台做具体的查询,将查询到的lis ...
- laravel PC内部方法调用
/** * [api 内部请求] * @author Foreach * @param string $method [请求方式] * @param string $url [地址] * @param ...
- Niagara 泵阀
1.泵阀系统 2.Niagara 每次在启动workbench的时候安装一下daemon,后启动platform 启动station的时候,当station的status变成Running之后启动
- java----微服务架构
参考文档 https://topsale.gitbooks.io/java-cloud-dubbo/content/ 单体应用: 项目的架构完完全全属于传统的 MVC 架构,所有的子系统都集成在一个很 ...
- java----面对对象
面对对象: public class Demo { public static void main(String[] args){ Horse h = null; h = new Horse(); / ...
- Python字典(Dictionary)
Python中字典与类表类似,也是可变序列,不过与列表不同,他是无序的可变序列,保存的内容是以键 - 值对的形式存放的.类似我们的新华字典,他可以把拼音和汉字关联起来,通过音节表可以快速的找到想要的字 ...
- 远程执行shell脚本
ssh -p2016 apache@10.10.18.130 '/bin/sh /data/www/vhosts/WOStest3_ENV/update_env.sh' 需要设置shell远程免密码登 ...
- js FileReader 笔记
以上传图片为例 通过input type='file' 上传完成图片后,获取图片 $('#input').files[0] var reader = new FileReader(); read ...
- centos7.4/rehat7.0系统安装
以下是安装过程:(图解),以下是rehat为例 这里可以改为centos的镜像 之后就可以用了,记得做快照!!! 拓展:分离使用 效果: