gevent StreamServer.start()似乎没有达到我的预期

时间:2012-04-23 20:17:51

标签: python networking concurrency gevent

我试图围绕gevent所采用的概念进行思考。这是gevent代码库中的一个示例。这是一个简单的回声服务器。

from gevent.server import StreamServer

# this handler will be run for each incoming connection in a dedicated greenlet
def echo(socket, address):
    print ('New connection from %s:%s' % address)
    socket.sendall('Welcome to the echo server! Type quit to exit.\r\n')
    # using a makefile because we want to use readline()
    fileobj = socket.makefile()
    while True:
        line = fileobj.readline()
        if not line:
            print ("client disconnected")
            break
        if line.strip().lower() == 'quit':
            print ("client quit")
            break
        fileobj.write(line)
        fileobj.flush()
        print ("echoed %r" % line)


if __name__ == '__main__':
    # to make the server use SSL, pass certfile and keyfile arguments to the constructor
    server = StreamServer(('0.0.0.0', 6000), echo)
    # to start the server asynchronously, use its start() method;
    # we use blocking serve_forever() here because we have no other jobs
    print ('Starting echo server on port 6000')
    server.serve_forever()

这看起来很简单,我的确有效。但正如评论中所说,serve_forever()是阻塞功能。如果我将最后一行更改为server.start(),程序将在执行每一行后停止。我做错了,但文档不是很有帮助。

在文档部分implementing servers with gevent中,它说当使用以下代码时,使用start()应为每个新连接生成一个新的greenlet:

 def handle(socket, address):
     print 'new connection!'

 server = StreamServer(('127.0.0.1', 1234), handle) # creates a new server
 server.start() # start accepting new connections

然后它说The server_forever() method calls start() and then waits until interrupted or until the server is stopped.我应该如何使用start()来运行服务器,以便它实际上保持活着以捕获第一个连接?

此外:

  1. start()serve_forever()之间的区别是什么?
  2. 在什么情况下我应该选择一个而不是另一个?
  3. 使用第一种方法时是否需要调用gevent.spawn()gevent.joinall(),但是某种程度上显而易见的是它们已被排除在StreamServer文档之外?

1 个答案:

答案 0 :(得分:9)

  1. start()是一个异步函数,它将服务器置于监听模式。但这并不妨碍您的程序退出,这是您的责任。
  2. 在简单的情况下,您可以使用serve_forever()。当您需要启动多个服务器或执行除启动服务器之外的其他操作时,start()会变得非常有用。
  3. 不,gevent.spawn()和gevent.joinall()与服务器无关。
  4. 使用gevent 1.0实际上最好使用gevent.wait()阻塞,直到没有更多活动连接/ greenlets / listeners / watchers。

    以下是一个示例:https://github.com/gevent/gevent/blob/master/examples/portforwarder.py