2012-05-15 68 views
3

我寫了一個簡單的tcp服務器,使用gevent.StreamServer進行測試。爲了讓我發送迴應給一些客戶端,我需要一種非阻塞的方式來通過raw_input()處理輸入,最好不使用線程。gevent.StreamServer和非阻塞raw_input()?

一些谷歌上搜索我碰到這個問題絆倒後:How to make non-blocking raw_input when using eventlet.monkey_patch() and why it block everything, even when executed on another thread?

我已經寫了下面的,它不正是我想要的,但是我認爲有它更好的辦法。有人能指出我正確的方向嗎?此外,爲什麼嘗試/除非沒有趕上KeyboardInterrupt的理念是值得讚賞的。

import select 
from gevent.monkey import patch_all 
from gevent.server import StreamServer 

patch_all(os=True, select=True) 

def raw_input(message): 
    """ Non-blocking input from stdin. """ 
    sys.stdout.write(message) 

    select.select([sys.stdin], [], []) 
    return sys.stdin.readline() 

def main(): 
    """ Run the server, listen for commands """ 

    server = StreamServer(("0.0.0.0", 6000), handle) 
    print "Starting server" 
    gevent.signal(signal.SIGTERM, server.close) 
    gevent.signal(signal.SIGQUIT, server.close) 
    gevent.signal(signal.SIGINT, server.close) 

    server.start() 
    while True: 
     try: 
      a = raw_input("") 
      if a: 
       print "Received %s" % a 
      gevent.sleep(0) 
     except KeyboardInterrupt: 
      print "Received a shutdown signal, going down ..." 
      server.stop() 
      sys.exit(0) 

if __name__ == "__main__": 
    main() 

編輯:我已經重寫了代碼的部分,我現在明白了main()中的愚蠢 - 功能。如果有人在這個問題上絆倒了,並且對如何做這件事有更好的想法,我會把它作爲一個編輯發佈。

from gevent.signal import signal 

def get_console_input(): 
    """ Non-blocking console input to the server """ 

    select.select([sys.stdin], [], []) 
    # There's quite a bit of code here but it is input handling so 
    # for shortness's sake I've snipped everything and return the line read. 
    return sys.stdin.readline() 

def exit(server): 
    """ Quit the server gracefully """ 

    print "Received shutdown signal, going down. """ 
    server.close() 
    sys.exit(0) 

def main(): 
    """ The main function. Create and run the server, listen for commands and 
    append any command to the server so it can send them on to the clients """ 

    # Myserver is a class which inherits from gevent.server.StreamServer. 
    # Myserver could just as well be replaced by gevent.server.StreamServer. 

    server = MyServer(("0.0.0.0", PORT)) 
    print "Starting server" 

    # Add some signal handlers to quit the server gracefully. 
    gevent.signal(signal.SIGTERM, exit, server) 
    gevent.signal(signal.SIGQUIT, exit, server) 
    gevent.signal(signal.SIGINT, exit, server) 

    # Server started in async mode 
    server.start() 

    while True: 
     get_console_input() 
     gevent.sleep(0) 

if __name__ == "__main__": 
    main() 

回答

5

我發現要做到這一點,最簡單的方法是使用gevent.socket.wait_read等到sys.stdin可以讀:

wait_read(sys.stdin.fileno()) 
return sys.stdin.readline() 

我也寫周圍的文件描述符小包裝給他們非阻塞.read().write()方法:https://gist.github.com/2915875

+0

謝謝,似乎完全是我要找的! – msvalkon

+0

在OSX中運行良好,但在Windows中似乎無法正常工作。 wait_read引發「IOError:[Errno 0]沒有錯誤」 –