zoukankan      html  css  js  c++  java
  • PYTHON2.day08

    前情回顾

    1. 进程间通信
        共享内存 : 在内存中开辟空间,只能存一组数据,效率
                    高
             Value() --> 单一数据
             Array() --> 存放数组,字符串等
       
        信号量 : Semaphore() 创建信号量
                  acquire() 消耗信号量
                  release() 增加信号量
    2.  什么是线程:
         线程特点
         创建多线程
            threading --> Thread

               Thread()  创建线程对象
            start()   启动线程
            join()    回收线程
        
         线程对象属性
            t.name  名称
            t.daemon 主线程退出后分支线程是否退出
            t.is_alive()  查看状态
            currentThread() 获取线程对象
        
         自定义线程类
            1. 继承Thread
            2. 编写自己的__init__
            3. 重写run

    线程通信
         1.通信方法:全局变量
         2. 同步互斥方法
            Event()
             e.set()  e.wait() e.clear()  e.is_set()

           Lock()
                 acquire()   release()

    4.线程的GIL问题
           全局解释器锁:同一时刻只有一个线程被解释,直接导致python线程效率低下
          

    一.测试
         1.结论:在无阻塞状态下,多线程程序和单线程程序执行效率几乎差不多,甚至还不如单线程效率
                 但是多线程运行相同的内容却可以有明显的效率提升
                
         2.python线程的GIL问题(全局解释器锁)
           【1】什么是GIL问题
                由于python 解释器设计中加入了解释器锁,
                导致python解释器同一时刻只能解释一个线程,大大降低了执行效率
           【2】导致后果,因为遇到阻塞时线程会让出解释器,去解释其他线程,
                所以python多线程在执行多阻塞高延迟IO时可以提升程序效率,
                其他情况并不能对效率有所提升
           【3】*尽量使用进程完成无阻塞的并发行为
                *不使用c作为解释器(java c#)
               
               
    二.进程线程的区别联系
         【1】区别和联系
             1.两者都是多任务编程方式,都能使用多核资源
             2.进程的创建删除消耗的计算机资源比线程多
             3.进程的空间多,数据不相干扰,有专门通信的方法:线程使用那些局部变量通信
             4.有个进程可以有多个分支线程,两者有包含关系
             5.多个线程共享进程资源,在共享资源操作时往往需要同步互斥处理
             6.进程线程在系统中都有自己的特有属性标志,如ID,代码段命令集等
          【2】使用场景
               1.任务场景:如果是相对独立的任务模块,可能使用多进程,
                           如果是多个分支共同形成一个整体任务可能用多线程
               2.项目结构:多种编程语言实现不同任务模块,可能是多进程,或者后端分离应该各自为一个进程
               3.难易程度:通信难度,数据处理的复杂度来判断进程间通信还是同步互斥
          【3】要求:1.对进程线程怎么理解/说说进程线程的差异
                     2.进程间通信有哪些,有什么特点
                     3.什么是同步互斥,什么情况下使用,用什么
                     4.给一个情形,说说用进程还是线程,为什么
                     5.同一个概念,僵尸进程的处理,GIL问题,进程状态。
                    
    三.网络通信模型   
             1.通信模型分类
                
                 【1】循环服务器模型:
                     循环接收客户端请求,处理请求,同一时刻只能处理一个请求,
                     处理完毕再处理下一个
                    
                     优点:实现简单占有资源少
                     缺点:无法同时处理多个客户端请求
                    
                     适用情况:处理的任务可以很快完成,客户端无需长期占用服务端程序,
                               udp比tcp更适合循环
                              
                 【2】IO并发模型:利用IO多路复用技术可以同时处理多个客户端IO请求
                    
                     优点:资源消耗少,能同时高效处理多个IO行为
                     缺点:只能处理并发的IO事件,无法处理cpu计算
                    
                     适用情况:HTTP请求,网络传输等都是IO行为,都可以充分可利用IO多路复用
                    
                【3】多进程/线程的网络并发模型:
                     每当一个客户端连接服务器,就创建一个新的进程/线程我该客户服务,
                     客户端退出时销毁该进程/线程

                    缺点:资源消耗较大
                     使用情况:客户点同时连接量较少,需要处理行为较复杂情况。
                    
             2.层多进程网络并发模型
                 【1】基于fork的并发模型
                     1.创建监听套接字
                     2.等待接收客户端请求
                     3.客户端连接创建新的进程处理客户端请求
                     4.原来进程继续等待其他客户端连接
                     5.如果客户端退出,则销毁的对应的进程
                    
    四.ftp文件服务器
         1.功能:
                 【1】分为服务端和客户端,要求可以有多个客户端同时操作
                 【2】客户端可以查看文件库中有什么样的文件
                 【3】客户端可以从文件库中下载文件到本地
                 【4】客户端可以上传文件到文件库
                 【5】使用print客户端打印输入提示,引导操作
         2.技术分析
           (1)使用fork多进程并发
           (2)tcp套接字传输
           (3)获取文件列表os.listdir()
              判断普通文件os.path.isfile()
         3.结构设计(操作流程)
           (1)客户端启动后打印界面
           (2)客户端发起请求后服务器要判断能否处理将结果反馈给客户端
           (3)若不能处理则终止请求行为,能处理子具体操作
           (4)将文件的具体功能封装为类
         4.具体功能分析      
           (1)搭建网络连接
           (2)查看文件列表
           (3)下载文件
           (4)上传文件
           (5)客户端退出
          

      1 #服务端
      2 '''ftp文件服务器
      3 fork server训练
      4 '''
      5 from socket import *
      6 import os,sys
      7 from time import sleep
      8 import signal
      9 import time
     10 
     11 #全局变量
     12 HOST = '0.0.0.0'
     13 PORT = 8888
     14 ADDR = (HOST,PORT)
     15 FILE_PATH = '/home/tarena/wenjan/'
     16 
     17 class FtpServer(object):
     18     def __init__(self,connfd):
     19         self.connfd = connfd
     20 
     21     def do_list(self):
     22         #获取文件列表
     23         file_list = os.listdir(FILE_PATH)
     24         if not file_list:
     25             self.connfd.send("文件库问空".encode())
     26             return
     27         else:
     28             self.connfd.send(b'OK')
     29             time.sleep(0.1)
     30 
     31         files = ""
     32         for file in file_list:
     33             if file[0] != '.' and os.path.isfile(FILE_PATH+file):
     34                 files = files + file + ','
     35 
     36         #将拼接好的字符串传给客户端
     37         self.connfd.send(files.encode())
     38 
     39 
     40 
     41     def do_get(self,filename):
     42         try:
     43             fd = open(FILE_PATH+filename,'rb')
     44         except IOError:
     45             self.connfd.send("文件不存在".encode())
     46             return
     47         else:
     48             self.connfd.send(b'OK')
     49             time.sleep(0.1)
     50         #发送文件内容
     51         while True:
     52             data = fd.read(1024)
     53             if not data:
     54                 time.sleep(0.1)
     55                 self.connfd.send(b'##')
     56                 break
     57             self.connfd.send(data)
     58 
     59 
     60     def do_put(self,filename):
     61         if os.path.exists(FILE_PATH + filename):
     62             self.connfd.send('文件存在'.encode())
     63             return
     64         try:
     65             fd = open(FILE_PATH+filename,'wb')
     66         except:
     67             self.connfd.send('上传失败'.encode())
     68             return
     69         self.connfd.send(b'OK')
     70         #接收文件
     71         while True:
     72             data = self.connfd.recv(1024)
     73             if data == b'##':
     74                 break
     75             fd.write(data)
     76         fd.close()
     77 
     78 
     79 
     80 def do_request(connfd):
     81     ftp = FtpServer(connfd)
     82     while True:
     83         data = connfd.recv(1024).decode()
     84         if not data or data[0] =='Q':
     85             connfd.close()
     86             return
     87         elif data[0] == 'L':
     88             ftp.do_list()
     89         elif data[0] =='G':
     90             filename = data.split(" ")[-1]
     91             ftp.do_get(filename)
     92         elif data[0] == 'P':
     93             filename = data.split(' ')[-1]
     94             ftp.do_put(filename)
     95 
     96 
     97 
     98 
     99 
    100 #网络搭建
    101 def main():
    102     #连接网络
    103     #创建套接字
    104     sockfd = socket()
    105     sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#循环
    106     sockfd.bind(ADDR)#绑定
    107     sockfd.listen(5)#监听
    108     print("Listen to the port 8888 ...")
    109     #处理僵尸进程
    110     signal.signal(signal.SIGCHLD,signal.SIG_IGN)
    111 
    112     while True:
    113         try:
    114             connfd,addr = sockfd.accept()
    115         except KeyboardInterrupt:
    116             sockfd.close()
    117             sys,exit("服务器退出")
    118         except Exception as e:
    119             print("服务器异常:",e)
    120             continue
    121         print("连接客户顿:",addr)
    122 
    123         #创建子进程处理客户端请求
    124         pid = os.fork()
    125         if pid ==0:
    126             sockfd.close()
    127             do_request(connfd)#处理客户端请求
    128             os._exit(0)
    129         #无论是父进程或者创建进程失败都是逊汗接收新的连接
    130         else:
    131             connfd.close()
    132 
    133 if __name__=="__main__":
    134     main()
    server.py

      1 #客户端
      2 from socket import *
      3 import sys
      4 import time
      5 
      6 #具体功能
      7 class FtpClient(object):
      8     def __init__(self,sockfd):
      9         self.sockfd = sockfd
     10 
     11 
     12     def do_list(self):
     13         self.sockfd.send(b'L')#发送请求
     14         #等待回复
     15         data = self.sockfd.recv(128).decode()
     16         if data =='OK':
     17             #接收文件名称
     18             data = self.sockfd.recv(4096).decode()
     19             files = data.split(',')
     20             for file in files:
     21                 print(file)
     22         else:
     23             #无法完成操作
     24             print(data)
     25 
     26 
     27     def do_quit(self):
     28         self.sockfd.send(b'Q')
     29         self.sockfd.close()
     30         sys.exit("谢谢使用")
     31 
     32 
     33     def do_get(self,filename):
     34         self.sockfd.send(('G '+filename).encode())
     35         data = self.sockfd.recv(128).decode()
     36         if data == 'OK':
     37             fd = open(filename,'wb')
     38             while True:
     39                 data = self.sockfd.recv(1024)
     40                 if data == b'##':
     41                     break
     42                 fd.write(data)
     43             fd.close()
     44         else:
     45             print(data)
     46 
     47     def do_put(self,filename):
     48         try:
     49             f = open(filename,'rb')
     50         except Exception:
     51             print("没有找打文件")
     52             return
     53         filename = filename.split('/')[-1]
     54         self.sockfd.send(('P '+filename).encode())
     55         data = self.sockfd.recv(128).decode()
     56         if data == 'OK':
     57             while True:
     58                 data = f.read(1024)
     59                 if not data:
     60                     time.sleep(0.1)
     61                     self.sockfd.send(b'##')
     62                     break
     63                 self.sockfd.send(data)
     64             f.close()
     65             print("%s上传完毕"%filename)
     66         else:
     67             print(data)
     68 
     69 
     70 
     71 #网络连接
     72 def main():
     73     #服务器地址
     74     ADDR = ('127.0.0.1',8888)
     75 
     76     sockfd = socket()
     77     try:
     78         sockfd.connect(ADDR)
     79     except Exception as e:
     80         print("连接服务器失败:",e)
     81         return
     82 
     83     #创建文件处理类对象
     84     ftp = FtpClient(sockfd)#把sockfd -->属性
     85 
     86 
     87     while True:
     88         print("
    -------------命令选项------------")
     89         print("***            list           ***")
     90         print("***           get  file       ***")
     91         print("***           put  file       ***")
     92         print("***              quit         ***")
     93         print("----------------------------------")
     94 
     95         cmd = input("输入命令>>")
     96         if cmd.strip() == 'list':
     97             ftp.do_list()
     98         elif cmd[:3] == 'get':
     99             filename = cmd.strip().split(' ')[-1]
    100             ftp.do_get(filename)
    101         elif cmd.strip() == 'quit':
    102             ftp.do_quit()
    103         elif cmd[:3] == 'put':
    104             filename = cmd.split(' ')[-1]
    105             ftp.do_put(filename)
    106         else:
    107             print("请输入正确命令")
    108 
    109 
    110 
    111 
    112 
    113 if __name__=="__main__":
    114     main()
    clent.py

    list

    get

    put
           quit
    作业:1.完成文件服务器上传功能
           2.复习http协议和httpserver1.0
           3.复习mysql的基本语句
           4.自己完成进程线程基础程序fork Process Thread

  • 相关阅读:
    剩余类&完全剩余组
    同余验算法
    一种快速余数求法
    同余的性质II
    同余初步
    求N个数的最小公倍数
    N个数GCD求解法
    快速求解GCD的三个Trick
    质数的几个有趣问题
    等比数列求和公式
  • 原文地址:https://www.cnblogs.com/shengjia/p/10420450.html
Copyright © 2011-2022 走看看