Sending and Receiving Data

Once a TCP connection is established, it can be used for communication. A program can send data to the computer on the other end, or respond to data received from the connection.

2.3.1. How Do I Do That?

Use a subclass of Protocol to send and receive data. Override the dataReceived method to control what happens when data is received from the connection. Use self.transport.write to send data.

Example 2-6 includes a class called DataForwardingProtocol, which takes any data received and writes it to self.output. This usage makes it possible to create a simple application, similar to the classic utility netcat, that passes any data received on standard input to a server, while printing any data received from the server to standard output.

Example 2-6. dataforward.py


from twisted.internet import stdio, reactor, protocol

from twisted.protocols import basic

import re



class DataForwardingProtocol(protocol.Protocol):

 def _ _init_ _(self):

 self.output = None

 self.normalizeNewlines = False



 def dataReceived(self, data):

 if self.normalizeNewlines:

 data = re.sub(r"(
|
)", "
", data)

 if self.output:

 self.output.write(data)



class StdioProxyProtocol(DataForwardingProtocol):

 def connectionMade(self):

 inputForwarder = DataForwardingProtocol( )

 inputForwarder.output = self.transport

 inputForwarder.normalizeNewlines = True

 stdioWrapper = stdio.StandardIO(inputForwarder)

 self.output = stdioWrapper

 print "Connected to server. Press ctrl-C to close connection."



class StdioProxyFactory(protocol.ClientFactory):

 protocol = StdioProxyProtocol



 def clientConnectionLost(self, transport, reason):

 reactor.stop( )



 def clientConnectionFailed(self, transport, reason):

 print reason.getErrorMessage( )

 reactor.stop( )



if __name__ == '_ _main_ _':

 import sys

 if not len(sys.argv) == 3:

 print "Usage: %s host port" % _ _file_ _

 sys.exit(1)



 reactor.connectTCP(sys.argv[1], int(sys.argv[2]), StdioProxyFactory( ))

 reactor.run( )

Run dataforward.py with two arguments: the host and port to connect to. Once connected, you can interact with the server from the command line. Anything you type will be sent to the server, and any data received from the server will be printed to your screen. For example, you can do a manual HTTP request to oreilly.com:


 $ python dataforward.py oreilly.com 80

 Connected to server. Press ctrl-C to close connection.

 HEAD / HTTP/1.0

 Host: oreilly.com

 <-- blank line

 HTTP/1.1 200 OK

 Date: Fri, 17 Dec 2004 06:25:53 GMT

 Server: Apache/1.3.33 (Unix) PHP/4.3.9 mod_perl/1.29

 P3P: policyref="http://www.oreillynet.com/w3c/p3p.xml",CP="CAO DSP COR CURa ADMa DEVa

 TAIa PSAa PSDa IVAa IVDa CONo OUR DELa PUBi OTRa IND PHY ONL UNI PUR COM NAV INT DEM

 CNT STA PRE"

 Last-Modified: Fri, 17 Dec 2004 00:58:06 GMT

 ETag: "8352-de9f-41c22f1e"

 Accept-Ranges: bytes

 Content-Length: 56991

 Content-Type: text/html

 X-Cache: MISS from www.oreilly.com

 Connection: close

 

2.3.2. How Does That Work?

Example 2-6 starts by defining a class called DataForwardingProtocol. Whenever this Protocol receives data, it will pass that data along to self.output (which can be any object with a write method) by calling self.output.write. DataForwardingProtocol has an attribute called normalizeNewLines. If this is set to true, it will normalize Unix-style newlines to the newlines used by most standard network protocols.

A subclass of DataForwardingProtocol, StdioProxyProtocol, does all the setup work. Once its connection is established, it creates a DataForwardingProtocol instance called inputForwarder and sets its output to self.transport. Then it wraps inputForwarder in an instance of the twisted.internet.stdio.StandardIO utility class, which hooks inputForwarder up to standard I/O instead of a network connection. This step has the effect of forwarding any data received on standard input to the StdioProxyProtocol's network connection. Finally, it sets the StdioProxyProtocol's output attribute to stdioWrapper, so that data received from the connection will be forwarded to standard output.

Once these protocols have been defined, it's simply a matter of defining StdioProxyFactory, which sets StdioProxyProtocol as its protocol, and handles stopping the reactor when the connection is closed (or fails). A call to reactor.connectTCP kicks off the connection attempt, and then control is given to the reactor with reactor.run( ).

Getting Started

Building Simple Clients and Servers

Web Clients

Web Servers

Web Services and RPC

Authentication

Mail Clients

Mail Servers

NNTP Clients and Servers

SSH

Services, Processes, and Logging



Twisted Network Programming Essentials
Twisted Network Programming Essentials
ISBN: 0596100329
EAN: 2147483647
Year: 2004
Pages: 107
Authors: Abe Fettig

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net