The previous labs in this chapter dealt with client connections, where an application initiated a connection to a remote server. However, Twisted can also be used for writing network servers, where the application waits for connections from clients. This lab will show you how to write a Twisted server that accepts connections from clients and interacts with them.
2.4.1. How Do I Do That?
Create a Protocol object defining your server's behavior. Create a ServerFactory object using the Protocol, and pass it to reactor.listenTCP. Example 2-7 shows a simple echo server that accepts a client connection and then repeats back all client messages.
Example 2-7. echoserver.py
from twisted.internet import reactor, protocol from twisted.protocols import basic class EchoProtocol(basic.LineReceiver): def lineReceived(self, line): if line == 'quit': self.sendLine("Goodbye.") self.transport.loseConnection( ) else: self.sendLine("You said: " + line) class EchoServerFactory(protocol.ServerFactory): protocol = EchoProtocol if __name__ == "_ _main_ _": port = 5001 reactor.listenTCP(port, EchoServerFactory( )) reactor.run( )
When you run this example, it will listen on port 5001, and report client connections as they are made:
$ python echoserver.py Server running, press ctrl-C to stop. Connection from 127.0.0.1 Connection from 127.0.0.1
In another terminal, use netcat, telnet, or the dataforward.py application from Example 2-6 to connect to the server. It will echo anything you type back to you. Type quit to close your connection:
$ python dataforward.py localhost 5001 Connected to server. Press ctrl-C to close connection. hello You said: hello twisted is fun You said: twisted is fun quit Goodbye. $ How does that work?
Twisted servers use the same Protocol classes as clients. To save some work, the EchoProtocol in Example 2-6 inherits from twisted.protocols.basic.LineReciever, which is a slightly higher-level implementation of Protocol. LineReceiver is a Protocol that automatically breaks its input into separate lines, making it easier to process a single line at a time. When EchoProtocol receives a line, it will echo it back to the clientunless the line is "quit", in which case it sends a goodbye message and closes the connection.
Next, a class called EchoServerFactory is defined. EchoServerFactory inherits from ServerFactory, the server-side sibling of ClientFactory, and sets EchoProtocol as its protocol. An instance of EchoServerFactory is then passed as the second argument to reactor.listenTCP, with the first argument being the port to listen on.