gevent中一个很大的改进就是将阻塞IO改为非阻塞IO,比如gevent.socket.patch就是将项目中阻塞socket变为非阻塞,因此深刻理解网络IO部分阻塞/非阻塞十分重要。
1.阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回
1)connect阻塞
![11.png](http://studygolang.qiniudn.com/161107/0e334e573c161053fe2190dff80c7334.png)
2)接收数据阻塞
![22.png](http://studygolang.qiniudn.com/161107/1b18eb2e967e8bb5ea08e5a25104f149.png)
2.非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回
1)接收数据非阻塞
![33.png](http://studygolang.qiniudn.com/161107/843641e14e87343dc44db543ea827236.png)
2)非阻塞面临的问题
![44.png](http://studygolang.qiniudn.com/161107/28f5fd90dce2e0bae38e0502da654aba.png)
源码
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 ' )
执行结果
![55.png](http://studygolang.qiniudn.com/161107/d2509fbc1bde3c0113e26fc694b51ecc.png)
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/
有疑问加站长微信联系(非本文作者)