• 网络IO


    一 网络IO

    recvfrom:
    wait data:等待客户端产生数据——》客户端OS--》网络--》服务端操作系统缓存
    copy data:由本地操作系统缓存中的数据拷贝到应用程序的内存中(速度很快)

    send:
    copy data

    网路IO的两个阶段(copy data阶段 + wait data阶段),换言之,所有IO都围绕这两个阶段

    讲IO模型的目的:自己实现gevent模块,解决单线程下的IO问题(网络IO,不含time.sleep)
    从而得到高性能。(之前讲的多进程和多线程并没有解决IO)



    1、阻塞IO模型
    wait data和copy data阶段一个都不能少,完完整整的等下来即为阻塞IO模型
    之前所接触的多进程、多线程、进程池、线程池(除了gevent模块以外)都是阻塞IO模型。


    2、非阻塞IO模型(更好的利用wait data阶段)

    非阻塞IO只能监测网络IO,不监测time.sleep()这种IO
    非阻塞IO有可能大规模占用CPU做无用操作,所以不推荐使用非阻塞IO

    服务端:

    from socket import *
    import time

    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)
    #不设置默认是True;将其设置成False,即将所有阻塞编程非阻塞(遇到等不到数据的情况,不阻塞,会抛出信息:BlockingIOError)
    #gevent模块中 monkey.patch_all() 即 s.setblocking(False)

    conn_l=[]
    while True:
    try:
    print('总连接数[%s]' % len(conn_l))
    conn,addr=server.accept()
    conn_l.append(conn)
    except BlockingIOError:
    del_l=[]
    for conn in conn_l:
    try:
    data=conn.recv(1024)
    if len(data) == 0:
    del_l.append(conn)
    continue
    conn.send(data.upper())
    except BlockingIOError:
    pass
    except ConnectionResetError:
    del_l.append(conn)

    for conn in del_l:
    conn_l.remove(conn)

    客户端:
    from socket import *
    import os

    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))

    while True:
    msg='%s say hello' %os.getpid()
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))


    3、多路复用IO模型

    IO多路复用可同时监测所有套接字,循环询问操作系统是否已准备好数据。
    当某个socket有数据到达了,就通知用户进程
    当只监测一个套接字时,多路复用比阻塞IO的效率还要低(之间多了通知应用程序,应用程序在向操作系统执行copy_data)
    一般会使用select模块帮忙完成IO多路复用模型



    客户端:

    from socket import *
    import time
    import select


    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)

    data_dic={}
    read_list=[server,]
    write_list=[]
    print('start....')
    while True:
    rl,wl,xl=select.select(read_list,write_list,[]) #read_list=[server,conn1,conn2,conn3,conn4]存放等到数据的对象(套接字)
    # print('read_list:%s rl:%s wl:%s ' %(len(read_list),len(rl),len(wl))) #rl=[conn1,conn2]
    for sk in rl: #rl为已经有等到信息的对象,可能为server,亦可为conn;当为s时,执行accept,当为conn时,执行recv
    if sk == server:
    conn,addr=sk.accept()
    read_list.append(conn) #建立好连接后,将连接丢入read_list中监测
    else:
    # sk.recv(1024)
    # print(sk)
    data=sk.recv(1024)
    write_list.append(sk)
    data_dic[sk]=data

    for sk in wl:
    sk.send(data_dic[sk].upper())
    data_dic.pop(sk)
    write_list.remove(sk)


    客户端:

    from socket import *
    import os

    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))

    while True:
    msg='%s say hello' %os.getpid()
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))



    4、异步IO模型

    异步IO模型的效率最高
    应用程序发起read操作之后,立刻就可以开始去做其它的事,
    kernel会等待数据准备完成,然后将数据拷贝到用户内存,
    当这一切都完成之后,kernel会给应用程序发送一个signal,告诉它read操作完成了。
  • 相关阅读:
    面向对象(静态,抽象,接口)--2017-04-20
    面向对象三大特性(面试经常问)--2017-04-18
    析构函数,函数重载,以及面向对象求面积的例子--2017-04-19
    密码强弱的判断(用正则表达式写)---2017-04-17
    php面向对象(一)---2017-04-17
    php数组--2017-04-16
    正则表达式 详解---2017-04-16
    JavaScript BOM 遗漏知识再整理;弹窗和记时事件;
    JavaScript HTML DOM---遗漏知识再整理(向html添加/删除元素,改变内容和css)
    bootstrap部分---网格系统;(几天没写博客了,为了潜心研究一下bootstrap)
  • 原文地址:https://www.cnblogs.com/kingyanan/p/9460056.html
Copyright © 2020-2023  润新知