非阻塞套接字和IO多路复用(三)

(一)同步阻塞IO模型

            1、IO就是输入和输出(即是读和写)     2、接收数据即为input,发送数据即为output的套接字      3、读文件即为input,写文件即为output  4、默认的套接字即为同步阻塞的套接字

(二)同步非阻塞IO模型

            1、概念:用户发起read请求,如果内核数据没有到达,立刻返回。然后不断循环的去发起read请求,直到有数据就进行读取操作。    2、缺点:用户线程每次请求IO都可以立即返回,但是为了拿到有内容的数据,需要不断轮询,这无非就要消耗大量的cpu内存。(在实际的生活很少使用这种模型,而是在其他IO模型中使用这种模型的特性)

(三)非阻塞套接字

            1、设置非阻塞:setblocking(False)    注意:当参数为True时,则为阻塞形式     2、accept、recv方法:这是两个阻塞方法,如果不阻塞,没有连接,没有数据会引发BlockingIoError,所以要用try.....except来捕获异常。

(四)同步非阻塞套接字实现并发服务器

            思路:外循环不断用accept来接受连接,用一个列表把所有连接进来的对象存储进来,并把服务器端的socket对象设置为非阻塞。内循环用来对列表里的连接对象进行操作。

             代码实例:import socket

                                server=socket.socket()

                                server.setblocking(False) #设置非阻塞

                                server.bind((' ',端口号))

                                server.listen(5)

                                client_list=[ ] #用来存储连接进来的客户端

                                while True:

                                        try:

                                                conn,adrr=server.accept()

                                                conn.setblocking(False)

                                                client_list.append((conn,addr))

                                                  print('连接:{}'.format(addr))

                                           except Exception:

                                                   pass

                                            for  client,adrr in client_list:

                                                      try:

                                                                recv_data=client.recv(1024)

                                                                if recv_data:

                                                                    print(recv_data.decode())

                                                                 else:

                                                                      client_list.remove((client,adrr))

                                                                        client.close()

                                                        except Exception:

                                                                    pass

(五)IO多路复用

            1、epoll只在linux系统下存在;windows中没有,但是有select。    2、epoll本质是事件驱动Io。    3、使用步骤:(1)创建epoll    (2)创建回调函数    (3)注册socket对象    (4)循环监听

(六)代码实例

               通过epoll、Io多路复用来实现并发服务器

                import socket

                import selectors

                server=socket.socket()

                sever.bind((' ',端口号))

                server.listen(10000)

                 def  recv(soc):

                        data=soc.recv(1024)

                         if data:          

                               soc.send(data)

                          else:

                                    epoll_selector.unregister(soc)

                                     soc.close()

                      def  accept(soc):

                                   conn,adrr=soc.accept()

                                    epoll_selector.register(

                                    conn,

                                    selectors.EVENT_READ,

                                       recv)

                    if  __name=='__main__':

                            epoll_selector.DefaultSelector()

                            epoll_selector.register(

                                 server,

                                  selectors.EVENT_READ,

                                  accept  )

                                while True:

                                        events=epoll_selector.select()

                                        for key,mark in events:

                                                sock=key.filedobj

                                                 callback=key.data

                                                  callback(sock)

你可能感兴趣的:(非阻塞套接字和IO多路复用(三))