天天看點

gevent基礎之阻塞與非阻塞詳解

gevent中一個很大的改進就是将阻塞IO改為非阻塞IO,比如gevent.socket.patch就是将項目中阻塞socket變為非阻塞,是以深刻了解網絡IO部分阻塞/非阻塞十分重要。

1.阻塞調用是指調用結果傳回之前,目前線程會被挂起。函數隻有在得到結果之後才會傳回

1)connect阻塞

gevent基礎之阻塞與非阻塞詳解

   2)接收資料阻塞

gevent基礎之阻塞與非阻塞詳解

2.非阻塞指在不能立刻得到結果之前,該函數不會阻塞目前線程,而會立刻傳回

1)接收資料非阻塞

gevent基礎之阻塞與非阻塞詳解

    2)非阻塞面臨的問題

gevent基礎之阻塞與非阻塞詳解

源碼

1.代碼示例

import logging

import time

import errno

logging.basicConfig( level=logging.DEBUG ,

                    format='%( name ) s : % ( message ) s ' , )

if __name__ == '__main__':

    import socket

    ip = ' localhost '

    port = 58562

    logger = logging.getLogger ( ' client ' )

    # Connect to the server

    logger.debug( ' creating socket ' )

    s = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )

    logger.debug( ' connecting to server ' )

    s.setblocking(0)

    try:

        s.connect( ( ip , port ) )

    except socket.error , msg :

        if msg[0] != errno.EINPROGRESS :

            logger.debug( ' error ' )

            exit(1)

    #time.sleep(1)

    # Send the data

    message = ' Hello , world '

    #len_sent = s.send ( message )

    logger.debug( ' sending data: "%s"', message )

    while True :

        try:

            len_sent = s.send ( message )

            break

        except socket.error, msg :

            if msg[0] != errno.EAGAIN:

                exit(1)

    # Receive a response

    logger.debug( ' waiting for response ' )

    while True:

        try:

            response = s.recv( len_sent )

            break

        except socket.error, msg:

            if msg[0] != errno.EAGAIN:

                exit(1)

    logger.debug( ' response from server: "%s"', response )

    # Clean up

    logger.debug( ' closing socket ' )

    s.close()

    logger.debug( ' done ' )

執行結果

gevent基礎之阻塞與非阻塞詳解

2.代碼示例

import logging

import sys

import SocketServer

import time

logging.basicConfig(level=logging.DEBUG ,

                    format='%( name ) s : % ( message ) s ' ,

                    )

class EchoRequestHandler ( SocketServer.BaseRequestHandler ) :

    def __init__( self , request , client_address , server ) :

        self.logger = logging.getLogger ( ' EchoRequestHandler ' )

        self.logger.debug( ' __init__ ' )

        SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)

        return

    def setup ( self ) :

        self.logger.debug( ' setup ' )

        return SocketServer.BaseRequestHandler.setup ( self )

    def handle ( self ) :

        self.logger.debug( ' handle ' )

        # Echo the back to the client

        data = self.request.recv ( 1024 )

        self.logger.debug( ' recv()->"%s"', data )

        self.request.send( data )

        return

    def finish ( self ) :

        self.logger.debug( ' finish ' )

        return SocketServer.BaseRequestHandler.finish(self)

class EchoServer(SocketServer.TCPServer):

    def __init__(self, server_address, handler_class=EchoRequestHandler):

        self.logger = logging.getLogger (' EchoServer ' )

        Self.logger.debug ('__init__')

        SocketServer.TCPServer.__init__(self, server_address, handler_class)

        return

    def server_activate ( self ) :

        Self.logger.debug ( ' server_activate ' )

        SocketServer.TCPServer.server_activate ( self )

        return

    def serve_forever ( self ) :

        self.logger.debug( ' waiting for reques t ' )

        Self.logger.info ( ' Handling requests , press <Ctrl-C> to quit ' )

        while True :

            self.handle_request()

        return

    def handle_request ( self ) :

        Self.logger.debug ( ' handle_request ' )

        return SocketServer.TCPServer.handle_request ( self )

    def verify_request ( self , request , client_address ) :

        Self.logger.debug ( ' verify_request ( %s , %s )', request, client_address)

        return SocketServer.TCPServer.verify_request(self, request, client_address )

    def process_request (self , request , client_address ) :

        Self.logger.debug ( ' process_request ( %s , %s ) ' , request , client_address )

        return SocketServer.TCPServer.process_request (self , request , client_address )

    def server_close ( self ) :

        Self.logger.debug ( ' server_close ' )

        return SocketServer.TCPServer.server_close ( self )

    def finish_request ( self , request , client_address ) :

        self.logger.debug('finish_request ( %s , %s ) ' , request , client_address )

        return SocketServer.TCPServer.finish_request(self , request , client_address )

    def close_request ( self , request_address ) :

        self.logger.debug ( ' close_request ( %s ) ' , request_address )

        return SocketServer.TCPServer.close_request ( self , request_address )

if __name__ == '__main__' :

    import socket

    import threading

    address = ( ' localhost ' , 0 ) # let the kernel give us a port

    server = EchoServer ( address , EchoRequestHandler )

    ip, port = server.server_address # find out what port we were given

    logger = logging.getLogger ( ' client ' )

    logger.info( ' Server on %s : %s ' , ip , port )

server.serve_forever ()

原文連結:http://www.maiziedu.com/wiki/frame/block/