开始 ----> 代码块A ---->代码块B ---->代码块C 。。。。。。 结束
每一个代码块都有各自实现的功能,按照条件语句顺序判断执行,每一次运行顺序或许都不一样,它的控制流程是由获取的数据所和判断语句所决定的。编程
开始 ----> 初始化 ----> 等待
事件驱动器启动后,在等待事件触发,而后作出相应的程序执行效果。触发事件包括:输入信息、鼠标、敲击键盘、内部定时器等服务器
一个进程在执行某个任务时,另一个进程必须等待其执行完毕,才能继续执行网络
所谓同步,就是在发出一个功能调用时,在没有获得结果以前,该调用就不会返回。按照这个定义, 其实绝大多数函数都是同步调用。可是通常而言,咱们在说同步、异步的时候, 特指那些须要其余部件协做或者须要必定时间完成的任务。
当一个异步功能调用发出后,调用者不能马上获得结果多线程
当该异步功能完成后,经过状态、通知或回调来通知调用者。若是异步功能用状态来通知, 那么调用者就须要每隔必定时间检查一次,效率就很低(有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这实际上是一 种很严重的错误)。 若是是使用通知的方式,效率则很高,由于异步功能几乎不须要作额外的操做。至于回调函数,其实和通知没太多区别。
调用结果返回以前,当前线程会被挂起并发
函数只有在获得结果以后才会 将阻塞的线程激活。有人也许会把阻塞调用和同步调用等同起来,实际上他是不一样的。对于同步调用来讲不少时候当前线程仍是激活的,只是从逻辑上当前函数没有返回而已。
和阻塞IO对立app
在不能马上获得结果以前也会马上返回,同时该函数不会阻塞当前线程
只有高电平(1)或低电平(0)的时候才触发通知,只要在这两种状态就能获得通知,只要有数据可读,那么水平触发的epoll就当即返回异步
只有电平发生变化(高电平到低电平,或者低电平到高电平)的时候才触发通知,有数据可读,但没有新的IO活动到来,epoll不会当即返回socket
select优缺点对比async
select:轮询方式,遍历每一个监听对象是否有数据变更,效率较低函数
epoll:主动响应,主动提交数据变更提高效率
服务端
# -*- coding:utf8 -*- import socket,select test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定义socket通讯方式和通讯协议。socket.AF_INET基于网络通讯,socket.SOCK_STREAM基于TCP协议 test.bind(('127.0.0.1',8000)) # 定义通讯ID test.listen(5) # 定义最大通讯监听数 inputs = [test,] #定义监听socket对象的列表 while True: r,w,e = select.select(inputs,[],[],5) # select监听 socket 对象,后跟时间单位为秒 for obj in r: # 遍历监听对象列表 if obj == test: # 判断监听对象是否和上次遍历同样 conn,addr = obj.accept() # 被动接收套接字创建的链接 print('accepted',conn,'from',addr) inputs.append(conn) # 添加新socket对象到列表 else: msg = obj.recv(1024) # 定义接收字节信息 print('客户端发送的消息是:', msg) obj.send(msg.upper()) # 定义发送消息 print("服务监听中...")
服务监听中... 客户端发送的消息是: b'abc' 服务监听中... 客户端发送的消息是: b'aaa' 服务监听中...
客户端
# -*- coding:utf8 -*- import socket test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定义socket通讯方式和通讯协议。socket.AF_INET基于网络通讯,socket.SOCK_STREAM基于TCP协议 test.connect(('127.0.0.1',8000)) #定义通讯ID,服务器的地址和端口 while True: inp = input(">>>").strip() #用户输入发送内容 test.sendall(inp.encode('utf-8')) #定义发送内容 data = test.recv(1024) #定义接收字节信息 print('收到服务端的发来的消息是:',data)
>>>abc 收到服务端的发来的消息是: b'ABC' >>>aaa 收到服务端的发来的消息是: b'AAA' >>>
服务端
#-*- coding:utf-8 -*- import selectors,socket sel = selectors.DefaultSelector() # 操做系统自识别合适的IO多路复用方式 def accept(sock,mask): conn,addr = sock.accept() # 被动接收套接字创建的链接 conn.setblocking(False) # 设置非阻塞 sel.register(conn,selectors.EVENT_READ,read) # conn 和 read 绑定,socket对象有活动调用accept方法 def read(conn,mask): try: # 异常代码检测防止某个客户端断开链接致使服务终止 data = conn.recv(1024) # 接收数据 if not data: # 判断是否接收到数据 raise Exception conn.send(data.upper()) # 接收到数据并返回数据 except Exception as e: # 万能异常 sel.unregister(conn) # 没有接收到数据,解除conn绑定的函数 conn.close() # 关闭链接 sock = socket.socket() # 建立socket对象 sock.bind(('127.0.0.1',8000)) # 定义通讯ID绑定对象 sock.listen(100) # 定义最大通讯监听数 sock.setblocking(False) # 设置非阻塞 sel.register(sock,selectors.EVENT_READ,accept) # socket 和 accept 绑定,socket对象有活动调用accept方法 print("服务运行中....") while True: events = sel.select() # 监听socket对象 for key,mask in events: # 遍历events对象列表 callback = key.data # 触发socket绑定的函数accept callback(key.fileobj,mask) # 监听到的有相应的socket对象
服务运行中....
客户端
# -*- coding:utf8 -*- import socket test = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #定义socket通讯方式和通讯协议。socket.AF_INET基于网络通讯,socket.SOCK_STREAM基于TCP协议 test.connect(('127.0.0.1',8000)) #定义通讯ID,服务器的地址和端口 while True: inp = input(">>>").strip() #用户输入发送内容 test.sendall(inp.encode('utf-8')) #定义发送内容 data = test.recv(1024) #定义接收字节信息 print('收到服务端的发来的消息是:',data)
>>>abc 收到服务端的发来的消息是: b'ABC' >>>