# 讲一下IO # 同步调用:串行,从上到下,等待结果完了在执行下一个。 # 异步调用:并发,直接扔进去,不用等待,并发执行 异步一般跟回调机制一起用 # # 同步 不等于 IO堵塞 # # 堵塞:就是遇到IO了,一般线程遇到IO,cup资源就走了, 协程是为了解决cup继续执行本线程 # 举个例子:家教老师,来上课,我还没准备好,老师说我先去别人家上课一会再回来,有了协程以后,相当于,我哥说:先给我补课吧,一会再给我弟弟补课 # # 非堵塞:相反 # # # 套接字下:阻塞IO和非阻塞IO # 阻塞IO:就是之前写的代码,他会一直等待,accept,recv和send都是IO # accept和recv:等待对方的数据,把数据从操作系统缓冲区拷贝到程序缓冲区 # send:直接把数据从程序缓冲区,发送到操作系统缓冲区 # # 非阻塞IO: # import socket # master = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # # #加上这句代码: # master.setblocking(False) # 不许堵塞 # while 等待数据 # 问:有数据了吗? # 答:给你个信号。现在没数据,你可以干别的事 # 有数据以后,就连接成功。 # 非堵塞IO的缺点: # 干别的事情的时候,消息来了,不能及时响应 # while死循环,没有堵塞,一直询问都是没用的,会导致CUP做无用功。 # 所以说不建议使用 # import socket # master = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # master.bind(("127.0.0.1",8080)) # master.listen(5) # master.setblocking(False) #非堵塞IO # con_list = [] # w_list = [] # while True: # try: # con,a=master.accept() # con_list.append(con) # pass # except BlockingIOError: # # print("干别的事情") # del_list = [] # # for con in con_list: # try: # data = con.recv(1024) # if not data: # del_list.append(con) # continue # #send 也是IO,怎么办,放到一个列表里,待会去处理 # # con.send(data.decode("utf-8").upper().encode("utf-8")) # w_list.append((con,data.decode("utf-8").upper().encode("utf-8"))) # except BlockingIOError: # continue # except Exception: # pass # con.close() # del_list.append(con) # del_wlist = [] # for item in w_list: # try: # item[0].send(item[1]) # del_wlist.append(item) # except BlockingIOError: # pass # for item in del_wlist: # w_list.remove(item) # for con in del_list: # con_list.remove(con) # master.close() # 客户端 # import socket # # client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # # client.connect(("127.0.0.1",8080)) # # while True: # data = input("<<<<") # client.send(data.encode("utf-8")) # data = client.recv(1024) # print(data.decode("utf-8")) # client.close() # 多路复用IO模型:包括等待数据,拷贝数据 和 中介 # 链接多了以后,效率就高了 # 一个链接的时候肯定比堵塞IO效率低 # 玩法:select # 优点:可以监控多个套接字,效率比堵塞要高,比非堵塞也高 # 缺点:随着监控的越多,那就效率越低,因为他是列表遍历 # poll只是比select监控的要多 # 要解决,还得靠epoll # epoll 只支持linux 不支持windows,我也是醉了 # import select # import socket # # master = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # master.bind(("127.0.0.1",8080)) # master.listen(5) # master.setblocking(False) # # rlist = [master,] # wlist = [] # wdata = {} # while True: # rl,wl,xl =select.select(rlist,wlist,[],0.5) # # print("rl:",rl) # # print("wl:",wl) # # print("xl:",xl) # # for i in rl: # if i == master: # con,a = i.accept() # rlist.append(con) # else: # try: # data = i.recv(1024) # if not data: # i.close() # rlist.remove(i) # continue # wlist.append(i) # wdata[i] = data.decode("utf-8").upper().encode("utf-8") # except Exception: # i.close() # rlist.remove(i) # del_wlist = [] # for i in wl: # i.send(wdata[i]) # del_wlist.append(i) # # for i in del_wlist: # wlist.remove(i) # wdata.pop(i) # 异步IO模型,这个暂时等爬虫的时候再深究 # 用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。 # # #
View Code
基于套接字的IO模型:
1.堵塞IO
2.非堵塞IO
3.多路复用IO
4.异步IO模型