网络编程与并发编程 11
一、远程执行命令
struct模块的应用
import struct
res=struct.pack('i',1333123129)
print(res,len(res))
recv_header=struct.unpack('i',res)
print(recv_header[0])
服务端
import socket
import subprocess
import struct
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)
# 链接循环
while True:
conn,addr=server.accept()
print(addr)
# 通信循环
while True:
try:
cmd=conn.recv(1024)
if len(cmd) == 0:break # 针对linux
obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_res=obj.stdout.read()
stderr_res=obj.stderr.read()
total_size=len(stdout_res) + len(stderr_res)
print(total_size)
# 1、先发送数据的总大小
conn.send(struct.pack('i',total_size))
# 2、再发送真实的数据
conn.send(stdout_res)
conn.send(stderr_res)
except Exception: # 针对windows
break
conn.close()
server.close()
客户端
import socket
import struct
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
# 1、先拿到数据的总大小
header_bytes=client.recv(4)
header=struct.unpack('i',header_bytes)
total_size=header[0]
# 2、再接收数据
recv_size=0
res=b''
while recv_size < total_size:
data=client.recv(1024)
recv_size+=len(data)
res+=data
print(res.decode('gbk'))
二、解决粘包问题
struct模块的应用
import struct
import json
header_dic={
'filenme':"a.txt",
'md5':"sdfasfdasfdasfd123123213",
"total_size":999999912343123442802
}
header_json=json.dumps(header_dic)
header_json_bytes=header_json.encode('utf-8')
# print(header_json_bytes)
# print(len(header_json_bytes))
服务端
import socket
import subprocess
import struct
import json
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)
# 链接循环
while True:
conn,addr=server.accept()
print(addr)
# 通信循环
while True:
try:
cmd=conn.recv(1024)
if len(cmd) == 0:break # 针对linux
obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_res=obj.stdout.read()
stderr_res=obj.stderr.read()
total_size=len(stdout_res) + len(stderr_res)
print(total_size)
header_dic = {
'filenme': "a.txt",
'md5': "sdfasfdasfdasfd123123213",
"total_size": total_size
}
header_json = json.dumps(header_dic)
header_json_bytes = header_json.encode('utf-8')
# 1、先发送报头的长度
conn.send(struct.pack('i',len(header_json_bytes)))
# 2、再发送报头
conn.send(header_json_bytes)
# 3、然后发送真实的数据
conn.send(stdout_res)
conn.send(stderr_res)
except Exception: # 针对windows
break
conn.close()
server.close()
客户端
import socket
import struct
import json
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
# 1、先拿到报头的长度
header_json_bytes_size=struct.unpack('i',client.recv(4))[0]
# 2、再收报头
header_json_bytes=client.recv(header_json_bytes_size)
header_json=header_json_bytes.decode('utf-8')
header_dic=json.loads(header_json)
print(header_dic)
# 3、最后接收数据
total_size=header_dic['total_size']
recv_size=0
res=b''
while recv_size < total_size:
data=client.recv(1024)
recv_size+=len(data)
res+=data
print(res.decode('gbk'))
三、基于udp协议的套接字通信
服务端
# import socket
from socket import *
import time
server=socket(AF_INET,SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
data,client_addr=server.recvfrom(1024)
time.sleep(10)
server.sendto(data.upper(),client_addr)
客户端
# import socket
from socket import *
client = socket(AF_INET, SOCK_DGRAM)
while True:
msg=input('>>>: ').strip()
client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'))
四、socketserver模块
TCP协议
服务端
import socketserver
class MyrequestHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request # conn对象
print(self.client_address)
while True:
try:
data=self.request.recv(1024)
if len(data) == 0:break
self.request.send(data.upper())
except Exception:
break
self.request.close()
if __name__ == '__main__':
s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyrequestHandler)
s.serve_forever()
客户端
import socket
import struct
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
udp协议
服务端
import socketserver
import time
class MyrequestHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request # conn对象
data=self.request[0]
self.request[1].sendto(data.upper(),self.client_address)
time.sleep(10)
if __name__ == '__main__':
s=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyrequestHandler)
s.serve_forever()
客户端
# import socket
from socket import *
client = socket(AF_INET, SOCK_DGRAM)
while True:
msg=input('>>>: ').strip()
client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'))
五、异常处理
1、什么是异常
异常是错误发生的信号,程序中一旦出现错误,python就会产生一个异常 一旦该异常没有被处理,该异常就会抛出来,程序的运行也随即终止
2、为何要处理异常
为了增强程序的容错性、鲁棒性、健壮性
3、异常的三个组成部分
异常的追踪信息 异常的类型 异常的内容
4、错误=》异常
4.1 语法错误:SyntaxError
应该在程序运行前就改正
4.2 逻辑错误
age=input(">>: ").strip()
if age.isdigit():
age=int(age)
print(age > 10)
5、异常处理的语法
try:
代码1
代码2
代码3
except 异常类型1 as e:
处理异常的代码1
except 异常类型2 as e:
处理异常的代码2
except (异常类型3,异常类型4,异常类型5) as e:
处理异常的代码3
except Exception as e:
处理异常的代码4
else:
被监测的代码块没有发生异常时执行的代码
finally:
无论被监测的代码块有无异常都会执行该代码
print('===>other code<====')
try不能单独和else连用,如果要用else,必须配合except
try:
print(111)
print(222)
print(3333)
except Exception:
pass
else:
print('ok')
print('===>other code<====')
try:
print('start...')
l=[]
l[100]
print('end...')
except KeyError as e:
print("Key错误:",e)
except IndexError as e:
print("索引错误:",e)
except Exception:
pass
print('===>other code<====')
try:
执行sql1
执行sql2
执行sql3
执行sql4
执行sql5
except Exception:
执行回滚操作
else:
执行提交操作
print('===>other code<====')
try:
print(1111)
sadf
print(2222)
print(33333)
finally:
print('====>finally')
# 回收资源
=======================断言===================
# 上半部分
print(111)
print(222)
print(333)
names=['egon','jack',]
# if len(names) != 3:
# raise Exception("数据错误")
assert len(names) == 3
# 下半部分
print(names[2])
=======================raise主动抛出异常===================
class NameType(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return "<%s>" %self.msg
class People:
def __init__(self,name):
self.__name=name
class Animal:
def speak(self):
raise Exception("必须定义speak方法")
def run(self):
raise Exception("必须定义run方法")
class Dog(Animal):
pass
class People(Animal):
pass
obj1=Dog()
obj2=People()
obj1.speak()
# obj1.run()
六、操作系统发展史
多道技术
空间上的复用:将内存分为几部分,每个部分放入一个程序,这样,同一时间内存中就有了多道程序。 时间上的复用:当一个程序在等待I/O时,另一个程序可以使用cpu,如果内存中可以同时存放足够多的作业,则cpu的利用率可以接近100%,类似于我们小学数学所学的统筹方法。(操作系统采用了多道技术后,可以控制进程的切换,或者说进程之间去争抢cpu的执行权限。这种切换不仅会在一个进程遇到io时进行,一个进程占用cpu时间过长也会切换,或者说被操作系统夺走cpu的执行权限)
程序
一堆代码文件
进程
一个正在运行的程序or程序的运行过程
并发:
多个进程/任务看起来是同时运行的
并行:
多个进程/任务是真正意义上的同时运行
进程的三种运行状态
运行态
就绪态
阻塞态
任务的提交方式
同步
异步
七、开启子进程
方式一:
from multiprocessing import Process
import time
def task(n):
print('starting...',x)
time.sleep(n)
print('end...')
x = 100
if __name__ == '__main__':
p=Process(target=task,args=(3,))
p.start() # 发生系统调用,让操作系统启动进程
print('主。。。。',x)
方式二
from multiprocessing import Process
import time
x = 100
class Myprocess(Process):
def __init__(self,n):
self.n = n
super().__init__()
def run(self) -> None:
print('starting...', x)
time.sleep(self.n)
print('end...')
if __name__ == '__main__':
p=Myprocess(3)
p.start()
print("主。。。")
八、进程空间彼此隔离
from multiprocessing import Process
import time
x = 100
def task(n):
global x
print('starting...')
time.sleep(n)
x=0
print('end...')
if __name__ == '__main__':
p=Process(target=task,args=(3,))
p.start() # 发生系统调用,让操作系统启动进程
time.sleep(10)
print('主。。。。',x)
from multiprocessing import Process
import time
import os
def task(n):
print(os.getpid(),os.getppid())
print('进程 %s starting...' %n)
time.sleep(n)
print('进程 %s end...' %n)
if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,))
p1.start() # 发生系统调用,让操作系统启动进程
p2.start() # 发生系统调用,让操作系统启动进程
p3.start() # 发生系统调用,让操作系统启动进程
start=time.time()
# time.sleep(10)
p3.join()
p1.join()
p2.join()
print(time.time() - start)
p3.terminate()
print(p3.is_alive())
print(p3.name)
print(p3.pid)
p3.join(1)
print('主。。。。',os.getpid())