gevent StreamServer.start() does not seem to do what I expect

concurrency, gevent, networking, python

Solution

- start() is an asynchronous function that puts a server in a listening mode. It does not prevent your program from exiting though, which is your responsibility.

- in simple cases you can use serve_forever(). start() becomes useful when you need to start multiple servers or do something else in addition to starting a server.

- no, gevent.spawn() and gevent.joinall() have nothing to do with servers.

With gevent 1.0 it's actually best to use gevent.wait() which blocks until there are no more active connections/greenlets/listeners/watchers.

Here's an example: https://github.com/gevent/gevent/blob/master/examples/portforwarder.py

Problem

I'm trying to wrap my brain around the concepts that gevent employs. Here's an example from the gevent code repository. It's a simple echo server. ``` 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() ``` That seems quite straightforward and I it works. However as it says in the comment that `serve_forever()` is a blocking function. If I change the last line to `server.start()` the program will stop after executing each line once. I am doing something wrong but the documentation is not very helpful. In the documentation section implementing servers with gevent, it says that using `start()` should spawn a new greenlet for each new connection when using the following code: ``` 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 ``` And then right after it says that `The server_forever() method calls start() and then waits until interrupted or until the server is stopped.` How am I supposed to run the server using `start()` so that it actually remains alive to catch the first connection? Also: - What is the difference between `start()` and `serve_forever()`? - In what contexts should I choose one over the other? - Are calls to `gevent.spawn()` and `gevent.joinall()` necessary when using the first method, but somehow so obvious that they've been left out of the StreamServer-documentation?

Original source