zhangyaqian

导航

 
4 May 18
复习:
1、 串行不是单纯的一个一个来,串行是按照规定好的顺序一个一个来
2、 listen(5): 规定的是最大的请求数;池: 规定的是最多连接数
3、 网络IO:收信息(wait + copy)和发消息(copy)
4、 多路复用IO可调用模块:
a、 select:本质是循环的问操作系统,随着元素的增加,效率降低
b、 poll:可以放下比select多的对象。但本质还是循环的问操作系统,随着元素的增加,效率降低。
c、 epoll:每个套接字都绑定一个回调函数,变被动为主动。Windows不支持epoll
d、 selector(更高程度的封装)为当前计算机在以上三种模块中选择效率最高的
5、 维持高并发的高效率模式:多进程+多线程+单线程下并发。例: BS架构中B/Nginx(sever)用的模式既以上模式
 
socketserver:
1、 多线程调: ThreadingTCPServer 或ThreadingUDPServer
2、 多进程调: ForkingTCPServer 或 ForkingUDPServer (Windows系统无法调用)
3、 ThreadingTCPServer: while循环+accept+启线程
4、 ThreadingUDPServer: while循环+recvfrom+启线程
5、 ThreadingTCPServer/ ThreadingUDPServer 传参时,bind&activate=True等价于bind + listen
6、 对TCP部分,用socketserver产生的self.request 等价于用socket产生的conn
7、 对UDP部分,用socketserver产生的self.request,为一个小元组,该元组的第一个元素为接收到的信息,第二个元素等价于用socket产生的server
8、 源码查看:
a、 主要的类分为三种类型(server(连接循环),request(通信循环),mixin(并发相关))
b、 看源码从执行入口开始看
c、 查看源码逻辑,可后续利用第三方源码封装自己的工具
9、 基于tcp
服务端:
import socketserver
 
# 通信循环
class MytcpHandler(socketserver.BaseRequestHandler):
    def handle(self): #socketserver规定的,必须使用
        while True:
            try:
                data = self.request.recv(1024)  # 1024 接收数据的最大限制
                if not data: break  # 针对linux系统
                self.request.send(data.upper())  # 注意:收发都是以bytes为单位
            except ConnectionResetError:
                break
        self.request.close()
 
if __name__ == '__main__':
    #连接循环
    server=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MytcpHandler)
    server.serve_forever()
    print(server.server_address)
    print(server.RequestHandlerClass)
print(server.socket) 
 
客户端:
import socket
 
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 
client.connect(('127.0.0.1',8080))
 
while True:
    msg=input('>>: ').strip()
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))
 
client.close()   
 
10   基于UDP
服务端:
import socketserver
 
# 通信循环
class MyUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # print(self.request)
        res=self.request[0]
        print('客户端发来的数据:',res)
 
        self.request[1].sendto(res.upper(),self.client_address)
 
if __name__ == '__main__':
    #连接循环
    server=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyUDPHandler)
server.serve_forever()
 
客户端:
import socket
import os
 
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 
while True:
    msg='%s hello' %os.getpid()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
 
    res,server_addr=client.recvfrom(1024)
print(res)
 
并发编程知识点总结
一 网络编程
                       目标:编写一个C/S或B/S架构的基于网络通信的软件
 
                       1、C/S,B/S(*****)
                                              server<===============>client
                                              服务端特点:
                                                                     1、不间断地提供服务
                                                                     2、服务端要支持并发+高性能
 
                       2、互联网
                                              互联网=物理连接介质+互联网协议(OSI七层***)
 
                                              tcp三次握手,四次挥手 (*****)
                                              tcp可靠,但不如udp效率高 (*****)
                                              udp不可靠,但效率高 (*****)
 
                       3、socket(*****)
                                              socket抽象层位于传输层与应用层之间
 
                       4、基于tcp协议的套接字通信(*****)
                                              加上连接循环
                                              加上通信循环
 
                       5、粘包问题:(*****)
                                              tcp流式协议独有的粘包问题
                                                                     解决方法:自定义报头
 
                                              udp数据报协议没有粘包问题
 
                       6、远程执行命令的小程序/上传下载文件的程序(*****)
 
                       7、基于udp协议的套接字通信(***)
 
二 并发编程
                       目标:让服务端能够支持高并发+高性能
 
                       1、               操作系统发展史
                                              多道技术(*****)
                                                                     产生背景:想要在单核下实现并发
                                                                     多道技术的核心:
                                                                                            1、空间上的复用(具体指的是内存中同时读入多道程序,多道程序的内存空间是物理隔离)
                                                                                            2、时间上的复用(复用cpu的时间)
                    切换+保存状态=》并发
 
                    切换:
                        1、遇到IO切换(可以提升效率)
                        2、运行时间过长或者有一个优先级更高的进程抢走了cpu(反而会降低效率)
 
                       2、进程
                                              1、进程理论(*****)
                                                  1、进程与程序区别
            2、并发与并行
            并发:看起来同时运行,单核就可以实现并发,但是单核无法实现并行
            并行:真正意义上的同时运行,一个cpu同一时刻只能做一件事
                 只有多核才能同时做多件事,即并行的效果
            串行:按照固定的顺序一个个地执行
                                                  3、不同操作系统开启子进程的区别
            4、一个进程的三种运行状态
 
                                              2、开启进程的两种方式(*****)
            了解:僵尸进程与孤儿进程(**)
 
                                              3、守护进程(**)
 
                                              4、互斥锁与信号量(**)
                                                  互斥锁就将并发变成一个一个的执行,牺牲了效率保证了数据安全
                                                  只有在多个任务修改共享的数据的时候才会考虑用互斥锁
 
                                              5、IPC机制:队列,管道(*)
 
                                              6、进程queue=管道+锁 (***)
 
                                              7、生产者消费者模型(*****)
                                                  1、什么是生产者消费者模型?
                                                      模型指的是解决问题的一种套路
                                                      该模型中包含两种重要的角色:
                                                          生产者:生产数据的任务
                                                          消费者:处理数据的任务
 
                                                  2、什么用生产者消费者模型?
                                                      在程序中有明显地两类任务,一类负责生产数据,另外一个类则拿到生产的数据进行处理,此时就应该
                                                      考虑使用生产者消费者模型来处理这种问题
 
                                                  2、为什么要用生产者消费者模型?好处?
                                                      1、将生产者与消费者解开耦合
                                                      2、平衡了生产者的生产数据的能力和消费者处理数据的能力
                                                          原理:
                        解耦和指的是生产者不与消费者直接打交道,
                        生产者可以不停地往队里里放数据
                        消费者可以不停地从队列里取走数据进行处理
 
                                                  3、如何实现?
 
                       3、线程
                                              1、线程理论(*****)
                                                  1、开一个进程内默认就有一个线程
                                                  2、线程vs进程
                                                      1、同一进程内的多个线程共享进程内的资源
                                                      2、创建线程的开销要远小于进程
 
                                              2、开启线程的两种方式(*****)
                                              3、守护线程(**)
                                              4、互斥锁与信号量(**)
                                              5、GIL vs 互斥锁(*****)
                                                  1、什么是GIL
                                                      GIL是全局解释器锁,是加到解释器身上的,
                                                      同一进程内的所有的线程,但凡执行,必须拿到解释器执行才能之心个,要拿到解释器必须先抢GIL
                                                      所以GIL可以被当做执行权限
 
                                                  2、GIL的影响
                                                      GIl会限制同一进程的内的多个线程同一时间只能有一个运行,也就说说python一个进程内的多线线程
                                                      无法实现并行的效果,即无法利用多核优势
 
                                                      然后多核提供的优势是同一时刻有多个cpu参与计算,意味着计算性能地提升,也就是说我们的任务是
                                                      计算密集型的情况下才需要考虑利用多核优势,此时应该开启python的多进程
 
                                                      在我们的任务是IO密集型的情况下,再多的cpu对性能的提升也用处不大,也就说多核优势在IO密集型程序面前
                                                      发挥的作用微乎其微,此时用python的多线程也是可以的
 
                                                  3、GIL vs 互斥锁
                                                      GIL保护的是解释器级别的数据
                                                      本质就是一个互斥锁,然后保护不同的数据就应该用不同的互斥锁,保护我们应用程序级别的数据必须自定义互斥锁
 
                                                      运行流程?
 
                                              6、死锁现象与递归锁(**)
                                              7、线程queue(***)
                                              8、Event事件(**)
 
                       4、池(*****)
                                              为何要用池:
                                                                     操作系统无法无限开启进程或线程
                                                                     池作用是将进程或线程控制操作系统可承受的范围内
                                              什么时候用池:
                                                                     当并发的任务数要远超过操作系统所能承受的进程数或
                                                                     线程数的情况应该使用池对进程数或线程数加以限制
 
                                              如何用池?
                                                                     池内装的东西有两种:
                                                                                            装进程:进程池
                                                                                            装线程:线程池
 
                                                                     进程线程池的使用
 
                                              提交的两种方式:
                                                                     同步调用
                                                                     异步调用+回调机制
 
                                                                     tpool=tpool=ThreadPoolExecutor(3)
                                                                     tpool.submit(task,arg1,agr2....).add_done_callback(handle)
 
                                              任务执行的三种状态:
                                                                     阻塞
                                                                                            阻塞
                                                                     非阻塞:
                                                                                            就绪
                                                                                            运行
 
                       5、单线程下实现并发(***)
                                              协程:在应用程序级别实现多个任务之间切换+保存状态
 
                                              高性能:
                                                                     单纯地切换,或者说么有遇到io操作也切换,反而会降低效率
                                                                     检测单线程下的IO行为,实现遇到IO立即切换到其他任务执行
 
                                              gevent
 
                       6、网络IO模型(主要掌握理论***)
                                              阻塞IO
                                              非阻塞IO
                                              IO多路复用
                                              异步IO
posted on 2018-05-07 07:52  zhangyaqian  阅读(109)  评论(0编辑  收藏  举报