python day28-day32

1、C/S B/S
client<---基于网络通信--->server
browser<---基于网络通信--->server

server 端必须满足的条件
  1、稳定运行(网络、硬件、操作系统、服务端应用软件),对外一直提供服务
  2.服务端必须绑定一个固定的地址

什么是互联网
  两大要素
    底层的物理连接介质,是为通信铺好道路的
    一套统一的通信标准---》互联网通信协议

 互联网协议就是计算机界的英语

自定义协议:

  任何一种通信协议都必须包含两部分

  1、报头:必须是固定长度

  2.   数据

标识地址的方式:

  ip+mac 就能标识全世界范围内独一无二的一台计算机

  ip+mac+port 就能标识全世界范围内独一无二的一个基于网络通信的应用软件

  url地址:标识全世界范围内独一无二的一个资源

  

OSI 五层协议 了解

tcp、协议

  三次握手建立连接

  四次挥手断开连接

  1、为何建连接要三次而断开连接却需要四次

  2、为何tcp协议是可靠协议,而udp协议是不可靠协议

  3、tcp协议建立连接与断开连接的状态信息以及表示的意义

半连接:

  限制的是同一时刻的请求数,而非连接数

tcp 协议粘包问题分析

  

#服务端

from socket import *

server=socket(AF_INET,SOck_STREAM)

server.bind(('127.0.0.1',8080))

server.listen(5)

conn,addr=server.accept()

print('第一次;',res1)

res2=conn.recv(1024)
print('第二次;',res2)

res3=conn.recv(1024)
print('第三次;',res3)


客户端

from socket import *

import time

client=socket(AF_INET,SOCK_STREAM)

client=connect('127.0.0.1',8080)

client.send(b'htime.sleeclient.send(b'world')

time.sleep(0.2)
client.send(b'egon'


模拟ssh远程执行命令
#服务端
from socket import *
import subprocess
import struct

server=socket(AF_INET,SOCK_STREAM)
server.bind(tupel_host_port)
server.listen(5)
while True:
  conn,client_addr=server.accpt()
  print('新的客户端',client_addr)

  while True:
    try:
      cmd=conn.recv(1025)
      if len(cmd)==0:break
    
      obj=subprocees.Popen(cmd.decode(encoding='utf-8'),
                   shell=True,
                   stderr=subprocess.PIPE,
                   stout=subprocess.PIPE)
      stout=obj.stdout.read()
      sterr=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()

#客户端

from socket import *
import struct

client=socket(AF_INET,SOCK_STREAM)
client.connect(tuple_host_port)
while True:
  cmd=input('>>:').strip()
  if len(cmd)==0: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:
  data=client.recv(1024)
  res+=data
  recv_size+=len(data)

print(res.decode(encoding='gbk'))




终极版 粘包问题解决
from socket import *
import subprocess
import struct
import json

server=socket(AF_INEF,SOCK_STREAM)
server.bind(tuple_host_port)
server.listen(5)

while True:
    conn,client_addr=conn.recv(1024)
    print('新的客户端',client_addr)
    
    while True:
        try:
            cmd=conn.recv(1024)
            if len(cmd)==0:break
            
            运行系统命令
            obj=subporcess.Popean(cmd.decode(encoding='utf-8'),sheel=True,
                         stderr=subprocess.PIPE,
                         stdout=subporcess.PIPE)
            s_out=obj.stdout.read()
            s_err=obj.stderr.read()
          
            header_dir={
             'file_name':'a.txt',
             'total_size':len(s_out)+len(s_err) ,
             'hash':'sdfsd'
            }
            先把报头的长度len(header_bytes)打包成4个bytes,然后发送出去
            conn.send(struct.pack('i',len(header_bytes)))
            发送报头
            conn.send(header_bytes)
            在发送真实的数据
            conn.send(s_out)
            conn.send(s_err)
    except ConnectionResetError:
      break
conn.close()



客户端
from socket import *
import struct
import json

client=socket(AF_INET,SOCK_STREAM)
client.connect(tuple_host_port)

while True:
    cmd=input('>>:').strip()
    if len(cmd)==0:continue
    client.send(cmd.encode('utf-8'))
    
    先收4个字节,该4字节中包含报头的长度
    header_len=struct.unpack('i',client.recv(4))[0]
    
    2/在接收报头
    header_bytes=client.recv(header_len)
    
    从报头中解析出想要的内容
    header_json=header_bytes.decode('utf-8')
    header_dic=json.loads(header_json)
    print(header_dic)
    total_size=header_dic['total_size']
    
    在收真实的数据
    recv_size=0
    res=b''
    while recv_size < total_size:
      data=client.recv(1024)
      res+=data
      recv_size+=len(data)
    print(res.decode(encoding='gbk'))

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

c/s
  server 必须遵循
    稳定运行,对外一直提供服务
    服务必须绑定ip和端口


上节课复习:
  1 粘包问题:
    tcp协议的nagle算法会将,数据量较小,并且发送时间间隔教短的多个数据包合并为一个发送
  2.如何解决粘包问题?
    自定义报头
今日内容:
  1、基于udp 协议的套接字通信
  2.socketserver模块
  3.操作系统的发展史=》多道技术*****
  4.什么是进程?为什么要用进程,开启进程的两种方式

  
  
操作系统原理:
  1 串行:一个任务完完整整地运行完毕后,才能运行下一个任务
  2 并发:看起来多个任务是同时运行的即可,单核也可以实现并发
  3 并行:真正意义上多个任务的同时运行,只有多核才实现并行
  4 cpu的功能
    cpu是用来做计算,cpu是无法执行IP操作,一旦遇到io操作,应该让cpu去执行别的任务


多道技术
  1.空间上的复用==》多个进程共用一个内存条
  2.时间上的复用==》多个进程复用同一个cpu时间
    cpu遇到io切换:可以提升效率
    一个进程占用cpu时间过长也会被切走:
        为了实现并发效果不得已而为之,反而会降低程序的执行效率

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

多道技术:
为何要进程:
  并发
如何用进程:
  开启进程的两种方式



udp
udp协议没有粘包问题
  
#服务端
import socket
server =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#称为数据报协议==》upp
server.bind(tuple_host_port)

data,client_addr=server.recvfrom(1)
print('第一次',clent_addr,data)

data,client_add=server.recvfrom(1024)
print('第二次',client_addr,data)

server.close()

#客户端
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报协议-》udp

client.sendto('hello'.encode('utf-8'),('127.0.0.1',8080))
client.sendto('world'.encode('utf-8'),('127.0.0.1',8080))
# client.sendto(''.encode('utf-8'),('127.0.0.1',8080))

client.close()



#基于socketserver 实现并发的socket(基于tcp协议)
#socketserver 方法实现 服务端
import socketserver
class MyHandler(socketserver.BaseRequestHandler):
  def handle(self):
    while True:
        print(self.client_address)
        print(self.request)
        #self.request=conn
        try:
          data=self.request.recv(1024)
          if len(data)==0:break
          self.request.send(data.upper())
         except ConnectionResetError:
          break
if __name__name=='__main__':
  s=socketserver.ThreadingTCPServer(tuple_host_port,Myhandler,bind_and_active=True)
  s.serve_forever()#代表连接循环
  #循环建立连接,每建立一个连接就会启动一个线程,
调用Myhanlder类产生一个对象,调用该对象下的handle方法,专门与刚刚建立好的连接做通信循环
#客户端
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080)) # 指定服务端ip和端口
while True:
# msg=input('>>: ').strip() #msg=''
msg = 'client33333' # msg=''
if len(msg) == 0:continue
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print(data)
phone.close()

#基于socketserver 实现并发的socket(基于udp协议)


import socketserver
class MyHandler(socketserver.BaseRequsetHandler)
  def handle(self):
    #通信循环
    #print(self.client_address)
    print(self.request)
    data=self.request[0]
    print('客户信息',data)
    self.request[1].sendto(data.upper),self.client_address)


if __name__=='__main__':
  s=socketserver.ThreadingUDPServer(tuple_host_port,MyHandler)
  s.serve_forver()
#用了这个客户端就可以多开,并且实现并发操作,Threadserve_forever,这里封装好的接口,底层是Thread,猜测:是基于线程实现的

#udp 客户端
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报协议-》udp

while True:
# msg=input('>>: ').strip() #msg=''
msg='client444444'

client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
data,server_addr=client.recvfrom(1024)
print(data)

client.close()


基于udp协议的套接字
#udp、 服务端

import socket
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#数据协议 --》udp
server.bind(tuple_host_port)

while True:
  data,client_addre=server.recvfrom(1024)
  print('====>',data,client_addr)
  server.sendto(data.upper(),client_addr)

server.close()


import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#数据报协议

while True:
  msg=input('>>:').strip()
  client.sendto(msg.encode('utf-8'),host_port_tuple)
  print(data)
client.close()


上节课复习:
  1、操作系统(现代操作系统):
    操作系统是位于计算机硬件与软件之间的控制程序
    作用: 1。将硬件的复杂操作封装成简单的接口,给用户或者应用程序使用
        2.将多个应用程序对硬件的竞争变得有序

  2.进程
    一个正在运行的程序,或者说是一个程序的运行过程
  3.串行、并发、并行
   串行:一个任务完完整整运行完毕,才执行下一个
   并发:多个任务看起来是同时运行的,单核就可以实现并发
  并行:多个任务是真正意义上的同时运行,只有多核才能实现并行

4.多道技术
  背景:想要在单核下实现并发(单核同一时刻只能执行一个任务)
  并发实现的本质就:切换+保存状态
  多道技术:
    1.空间上的复用=》多个任务共用一个内存条,但占用内存是彼此隔离的,而且是物理层面隔离的
    2.时间上的复用=》多个任务共用同一个cpu
      切换:
        1.遇到io切换
        2.一个任务占用cpu时间过长,或者有另外一个优先级更高的任务抢走cpu


今日内容:
  进程理论
  开启进程的两种方式
  进程对象相关的属性或者方法

线程:
  线程理论
  开启线程的两种方式
  先从对象相关的属性或方法


开启子进程的两种方式:
方式一:
from multiporcessing import Process
import time

def task(x):
  print('%s is runing '%x)
  time.sleep(3)
  print('%s is done '%x)

if __name__=='__main__':
  #两种写法:Process(target=task,kwargs={'x':'子进程'})
  p=Process(target=task,args=('子进程',))## 如果args=(),括号内只有一个参数,一定记住加逗号
  p.start()#只是在向操作系统发送一个开启子进程的信号,#运行起来取决于操作系统
  print('主')



from multiprocessing import process
import time

class Myporcess(Process):
  def __init__(self,x):
    super().__init__()
    self.name=x
  def run(self):
    print('%s is runing '%self.name)
    time.sleep(3)
    print('%s is done '%self.name)

if __name__=='__main__':
  p=Myprocess('子进程1')
  p.start()#等同于p.run()
  print('主')

from multiprocessing import Process
import time

def task(x,n):
  print('%s is runing'%x)
  time.sleep(n)
  print('%s is done'%x)

if __name__=='__main__':
  p1=Process(targest=task,args=('我是参数',3))# 如果args=(),括号内只有一个参数,一定记住加逗号
  p2=Process(targest=task,args=('我是参数2',5))
  p1.start() # 只是在操作系统发送一个开启子进程的信号
  p2.start()
  print('主‘)


进程内空间是彼此隔离的
from multiprocessing import Process
import time

x=100
def task():
global x
x=0
print('done')
if __name__ == '__main__':
p=Process(target=task)
p.start()
time.sleep(500) # 让父进程在原地等待,等了500s后,才执行下一行代码
print(x)

进程对象的方法或属性详解
#1、join
# from multiprocessing import Process
# import time
#
# def task(name):
# print('%s is running ' %name)
# time.sleep(3)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':
# p=Process(target=task,args=('子进程1',))
# p.start()
# p.join() # 让父进程在原地等待,等到子进程运行完毕后,才执行下一行代码
# print('主')



# from multiprocessing import Process
# import time
#
# def task(name,n):
# print('%s is running ' %name)
# time.sleep(n)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':
# p1=Process(target=task,args=('子进程1',1))
# p2=Process(target=task,args=('子进程2',2))
# p3=Process(target=task,args=('子进程3',3))
#
# start_time=time.time()
# p1.start()
# p2.start()
# p3.start()
#
# p3.join()
# p1.join()
# p2.join()
#
# stop_time=time.time()
# print('主',(stop_time-start_time))


# from multiprocessing import Process
# import time
#
# def task(name,n):
# print('%s is running ' %name)
# time.sleep(n)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':
# p1=Process(target=task,args=('子进程1',1))
# p2=Process(target=task,args=('子进程2',2))
# p3=Process(target=task,args=('子进程3',3))
#
# start=time.time()
# p1.start()
# p1.join()
# p2.start()
# p2.join()
# p3.start()
# p3.join()
#
# stop=time.time()
# print('主',(stop-start))


# from multiprocessing import Process
# import time
#
# def task(name,n):
# print('%s is running ' %name)
# time.sleep(n)
# print('%s is done ' % name)
#
#
# if __name__ == '__main__':
# # p1=Process(target=task,args=('子进程1',1))
# # p1.start()
# # p2=Process(target=task,args=('子进程2',2))
# # p2.start()
# # p3=Process(target=task,args=('子进程3',3))
# # p3.start()
#
# p_l=[]
# start=time.time()
# for i in range(1,4):
# p=Process(target=task,args=('子进程%s' %i,i))
# p_l.append(p)
# p.start()
#
# # print(p_l)
# for p in p_l:
# p.join()
#
# stop=time.time()
#
# print('主',(stop-start))



# pid
# from multiprocessing import Process
# import time
# import os
#
# def task(n):
# print('%s is running ' %os.getpid())
# time.sleep(n)
# print('%s is done ' % os.getpid())
#
#
# if __name__ == '__main__':
# p1=Process(target=task,args=(10,))
# # print(p1.pid)
# p1.start()
# print(p1.pid) # 父进程内查看子pid的方式
# print('主')


from multiprocessing import Process
import time
import os

def task():
print('自己的id:%s 父进程的id:%s ' %(os.getpid(),os.getppid()))
time.sleep(200)

if __name__ == '__main__':
p1=Process(target=task)
p1.start()
print('主',os.getpid(),os.getppid())
# 爹=》主--》儿子





# 了解
# from multiprocessing import Process,current_process
# import time
#
# def task():
# print('子进程[%s]运行。。。。' %current_process().name)
# time.sleep(200)
#
# if __name__ == '__main__':
# p1=Process(target=task,name='子进程1')
# p1.start()
# # print(p1.name)
# print('主')




# from multiprocessing import Process,current_process
# import time
#
# def task():
# print('子进程[%s]运行。。。。' %current_process().name)
# time.sleep(2)
#
# if __name__ == '__main__':
# p1=Process(target=task,name='子进程1')
# p1.start()
#
# # print(p1.is_alive())
# # p1.join()
# # print(p1.is_alive())
#
# p1.terminate()
# time.sleep(1)
# print(p1.is_alive())
# print('主')
 

什么是生产者消费者模式

  生产者:比喻的是程序中负责产生数据的任务

  消费者:比喻的是程序中负责处理数据的任务

  生产者 -》共享的介质(队列)<--消费者

为何用

  实现了生产者与消费者的解耦合,生产者可以不停地生产,消费者也可以不停地消费

从而平衡了生产者的生产能力与消费者的消费能力,提升了程序整体运行的效率

什么时候用?

  当我们的程序中存在明显的两类任务,一类负责产生数据,另外一类负责处理数据

此时就应该考虑使用生产者消费者模型来提升程序的效率

'
# from multiprocessing import Queue,Process
# import time
# import os
# import random
#
# def producer(q):
# for i in range(10):
# res='包子%s' %i
# time.sleep(random.randint(1,3))
# # 往队列里丢
# q.put(res)
# print('\033[45m%s 生产了 %s[0m' %(os.getpid(),res))
# q.put(None)
#
# def consumer(q):
# while True:
# #从队列里取走
# res=q.get()
# if res is None:break
# time.sleep(random.randint(1,3))
# print('\033[46m%s 吃了 %s[0m' %(os.getpid(),res))
#
# if __name__ == '__main__':
# q=Queue()
# # 生产者们
# p1=Process(target=producer,args=(q,))
# # 消费者们
# c1=Process(target=consumer,args=(q,))
#
# p1.start()
# c1.start()
#
# print('主')




# from multiprocessing import Queue,Process
# import time
# import os
# import random
#
# def producer(name,food,q):
# for i in range(3):
# res='%s%s' %(food,i)
# time.sleep(random.randint(1,3))
# # 往队列里丢
# q.put(res)
# print('\033[45m%s 生产了 %s\033[0m' %(name,res))
# # q.put(None)
#
# def consumer(name,q):
# while True:
# #从队列里取走
# res=q.get()
# if res is None:break
# time.sleep(random.randint(1,3))
# print('\033[46m%s 吃了 %s\033[0m' %(name,res))
#
# if __name__ == '__main__':
# q=Queue()
# # 生产者们
# p1=Process(target=producer,args=('egon','包子',q,))
# p2=Process(target=producer,args=('杨军','泔水',q,))
# p3=Process(target=producer,args=('猴老师','翔',q,))
# # 消费者们
# c1=Process(target=consumer,args=('Alex',q,))
# c2=Process(target=consumer,args=('wupeiqidsb',q,))
#
# p1.start()
# p2.start()
# p3.start()
# c1.start()
# c2.start()
#
# p1.join()
# p2.join()
# p3.join()
# # 在p1\p2\p3都结束后,才应该往队列里放结束信号,有几个消费者就应该放几个None
# q.put(None)
# q.put(None)

# print('主')


from multiprocessing import JoinableQueue,Process
import time
import os
import random

def producer(name,food,q):
for i in range(3):
res='%s%s' %(food,i)
time.sleep(random.randint(1,3))
# 往队列里丢
q.put(res)
print('\033[45m%s 生产了 %s\033[0m' %(name,res))
# q.put(None)

def consumer(name,q):
while True:
#从队列里取走
res=q.get()
if res is None:break
time.sleep(random.randint(1,3))
print('\033[46m%s 吃了 %s[0m' %(name,res))
q.task_done()

if __name__ == '__main__':
q=JoinableQueue()
# 生产者们
p1=Process(target=producer,args=('egon','包子',q,))
p2=Process(target=producer,args=('杨军','泔水',q,))
p3=Process(target=producer,args=('猴老师','翔',q,))
# 消费者们
c1=Process(target=consumer,args=('Alex',q,))
c2=Process(target=consumer,args=('wupeiqidsb',q,))
c1.daemon=True
c2.daemon=True

p1.start()
p2.start()
p3.start()
c1.start()
c2.start()

p1.join()
p2.join()
p3.join()

q.join() #等待队列被取干净
# q.join() 结束意味着
# 主进程的代码运行完毕--->(生产者运行完毕)+队列中的数据也被取干净了->消费者没有存在的意义

# print('主')

守护进程
  守护进程其实就是一个 子进程
守护=》伴随
  守护进程会伴随主进程的代码运行完毕后而死掉

为何用守护进程
  关键字就两个:
    进程:当父进程需要将一个任务并发出去执行,需要将任务放到一个子进程里
    守护:当该子进程内的代码在父进程代码运行完毕后就没有存在的意思了,就应该
        将该子进程设置为守护进程,会在父进程代码结束后死掉


from multiporcessing import Process
import time,os

def task(name):
  print('%s is runing '%name)
  time.sleep(3)

if __name__=='__main__':
  p1=Process(target=task,args=('守护进程',))
  p2=Process(target=task,args='正常的子进程',)
  
  p1.daemon=True #设置守护进程,一定要放在start 之前
  p1.start()
  p2.start()
  
  print('主')

  


#主进程代码运行完毕,守护进程就会结束
from multiprocessing import Process
import time
def foo():
  print(123)
  time.sleep()
  print('end 123')
def bar():
  print('sdfsd')
  time.sleep(3)
  print('end456')


if __name__=='__main__':
  p1=Process(target=foo)
  p2=Process(target=bar)
  
  p1.daemo=True
  p1.start()
  p2.start()

  print('main-----')




猜你喜欢

转载自www.cnblogs.com/yanxiatingyu/p/9315690.html
今日推荐