gevent基础之阻塞与非阻塞详解

maiziedu · 2016-11-07 05:46:29 · 3123 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2016-11-07 05:46:29 的主题,其中的信息可能已经有所发展或是发生改变。

  gevent中一个很大的改进就是将阻塞IO改为非阻塞IO,比如gevent.socket.patch就是将项目中阻塞socket变为非阻塞,因此深刻理解网络IO部分阻塞/非阻塞十分重要。

  1.阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回

  1)connect阻塞

11.png

  2)接收数据阻塞

22.png

  2.非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

  1)接收数据非阻塞

33.png

  2)非阻塞面临的问题

44.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

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/


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3123 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传