• 网络编程6(IO模型)


    IO  sock对象本质是文件描述符,什么是文件描述符,是一个非零的整数,内核区接受的数据,在用户拷贝完之后就没有了

    IO多路复用比阻塞IO的好处是可以监听多个sock对象,能处理多个连接,IO多路复用全程阻塞,能实现并发现象,一定不是同时聊,没有开多线程多进程

    什么是阻塞IO,(什么是非阻塞IO),主进程会一直卡住不能干其他事,知道对应的操作结束,非阻塞IO不会卡,

    阻塞IO全程阻塞,非阻塞IO,copydaty时进程阻塞,IO多路复用全程阻塞;这三个是同步IO模型,只有第四个异步IO全程无阻塞,但是实现麻烦,全程由操作系统完成(waitdata copydata)

     同步IO只要两个过程(wait data,copy data)有一个是阻塞的就叫同步IO

    同步:  阻塞IO  非阻塞IO  io多路复用(select epoll poll)
    异步:  异步IO

    IO模型有几个角色: 进程,操作系统(内核),IO都是进程的Io

    http://www.cnblogs.com/yuanchenqi/articles/6755717.html

    IO模型
    进程如果有数据的交换,进程发系统调用进入内核态,内核态的数据cp到用户空间,分两个过程,wait for data ,copy data


    阻塞IO




    非阻塞IO

     IO多路复用


     IO multiplexing这个词可能有点陌生,但是如果我说select,epoll,大概就都能明白了。有些地方也称这种IO方式为event driven IO。我们都知道,select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如图:

       当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
    这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom)。但是,用select的优势在于它可以同时处理多个connection。(多说一句。所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
    在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

    结论: select的优势在于可以处理多个连接,不适用于单个连接 

    总结##################################################################################

    IO就是进程有需要数据的时候才会产生IO系统调用,分两个阶段 1:wait for data;2: copy data

    阻塞IO全程阻塞(进程在需要IO调用的时候,用户程序发动系统调用,从用户态转到内核态(内核态是操作系统管理,有操作硬件的权限)直到数据从内核缓存区cp到用户区,此时内核的数据直接清除),

    非阻塞IO wait for data不阻塞,用户程序会隔一段时间就到内核区问问,数据准备好了没有,一次次的发起系统调用,直到有数据了,阻塞cp数据

    IO多路复用:这个最大的改善是用户程序调用select函数发起系统调用阻塞等数据,等数据到了,用户进程发起系统调用cp数据,然后清除内核缓存中的数据,比IO阻塞多了个系统调用,下面的例子多个客户端聊天
    就是及于此
    1 阻塞IO: 全程阻塞 2 非阻塞IO:
    优点:wait
    for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时接受的 两个阶段:wait for data:非阻塞 copy data :阻塞 3 IO多路复用(监听多个连接)
    sock::sock <socket.socket fd=224, 
    family=AddressFamily.AF_INET, 
    type=SocketKind.SOCK_STREAM, 
    proto=0, laddr=('127.0.0.1', 8800)>
    224就是文件打桩符
    对于文件描述符(套接字对象):
    1 是一个非零整数,不会变
    2 收发数据的时候,对于接收端而言,数据先到内核空间,
    然后copy到用户空间,同时,内核空间数据清除。
    
    特点:1 全程(wait for data,copy)阻塞
          2 能监听多个文件描述符
          
          实现并发
           
    4 异步IO
    
      全程无阻塞,
    
    
    5 驱动信号
    
    总结: 
    同步:  阻塞IO  非阻塞IO  io多路复用
    异步:  异步IO
    #server端
    #简单聊天,最大接受5个client排队,第一个连接后就进入while第二个,阻塞socket模块
    
    import socket
    import time
    
    sock=socket.socket()
    
    sock.bind(("127.0.0.1",8800))
    
    sock.listen(5)
    
    #sock.setblocking(False)
    
    # while 1:
    #     try:
    #         conn,addr=sock.accept()   # 阻塞等待链接
    #     except Exception as e:
    #         print(e)
    #         time.sleep(3)
    
    # data=conn.recv(1024)
    #
    # print(data.decode("utf8"))
    
    while 1:
        conn,addr=sock.accept()
        print("server working.......")
        while 1:
    
            data=conn.recv(1024)
            print(data.decode("utf8"))
            send_data=input(">>>")
            conn.send(send_data.encode("utf8"))
    
        conn.close()
    
    
    
    
    
    
    
    #client端
    
    
    
    import socket
    
    sock=socket.socket()
    
    
    sock.connect(("127.0.0.1",8800))
    
    while 1:
    
         data=input("input>>>")
         sock.send(data.encode("utf8"))
         rece_data=sock.recv(1024)
         print(rece_data.decode("utf8"))
    
    sock.close()
    #给予select机制实现多客户端并发聊天   如果几个客户端先后发消息过来,监控的列表中conn几个会有变化,server端会吧有变化的conn for遍历一遍回消息再
    
    #server端
    
    #sock是客户来连接才有变化,conn是客户发消息才有变化,主要还是解决IO操作
    
    
    
    import socket
    import time
    
    import select
    sock=socket.socket()
    
    sock.bind(("127.0.0.1",8800))
    
    sock.listen(5)
    
    
    sock.setblocking(False)
    inputs=[sock,]
    
    print("sock",sock)
    
    while 1:
        r,w,e=select.select(inputs,[],[])  # select只监听有变化的套接字 inputs=[sock,conn1,conn2,conn3..] #开启select首先到这,
        print("r",r)
        for obj in r:   # 第一次 [sock,]  第二次(客户端发消息) #[conn1,]
            if obj==sock:#客户端第一次连接走这条路
                print('change')
                conn,addr=obj.accept()
                inputs.append(conn)   #  inputs=[sock,conn]
    
            else:#客户端第二次发消息走这条路
                data=obj.recv(1024)
                print(data.decode("utf8"))
                send_data=input(">>>")
                obj.send(send_data.encode("utf8"))
    
    
    
    
    
    #client 端
    #跟上面的一样
  • 相关阅读:
    iOS4.3可显著选拔iPhone4和iPad速度
    传iPhone5回归金属机身 形状似touch4
    联发科月度收入跌至四年来冰点
    品评:上海电信业不可被摩登数据蒙住双眼
    分析师以为移动搜集运营商需开发数据赚钱新途径
    智能手机市场输家和赢家:Android手机厥后居上
    人大代表张新建:减速互联网及短信拘留立法
    思科任命尝试副总裁加里摩尔出任首席运营官
    运营商纷繁筹建移动付出公司
    2011年中国3G移动通讯市场瞻望与分析
  • 原文地址:https://www.cnblogs.com/wanchenxi/p/7857803.html
Copyright © 2020-2023  润新知