sending data to particular client from twisted server

python, python-2.7, twisted

Solution

self.transport.write("string")

In the examples you refer to, `self` is an instance of `Protocol` or a subclass of `Protocol` (or an object that provides `IProtocol` without subclassing `Protocol`, which is also completely fine).

`self.transport` is therefore an object that provides `ITransport` (perhaps it provides the more specific `ITCPTransport` or `ISSLTransport` but that's not important in the context of this question).

In Twisted, an object that provides `ITransport` represents a connection between two endpoints. Such a connection might be an IPv4/TCP connection or an IPv6/TLS connection or an AF_UNIX connection. What all of these kinds of connections have in common is that they have exactly two endpoints. Data can be "sent" from one endpoint and "received" at the other endpoint (and vice versa).

The reason `self.transport.write("string")` doesn't obviously include any addressing information is that `self.transport` already includes that information.

Since `self.transport` represents a connection (and only one connection: no more, no less) and every connection has two endpoints, the addresses of those two endpoints are necessarily part of `self.transport` (were they not, `self.transport` could not represent that connection).

And the object is actually slightly more specific than this: it represents one side of the connection. It knows which of the two endpoints is "here" and which is somewhere else. This means that when you write data to `self.transport` there is only one possible address to which it can be sent: the endpoint of the connection represented by `self.transport` which is not "here".

By convention, that endpoint has a name. It is the "peer". The interface `ITransport` defines a method, `getPeer`, which exposes to you the "peer" address of the connection the transport object represents. `self.transport.getPeer()` returns an object that represents that address. The exact shape of that object depends on what kind of connection you have.

You asked how can I choose particular client on basis of ip address. If it is really the case that data flowing through your system has its destination explicitly specified by an IP address then you can use `getPeer` to find a connection that matches the required address.

However, it is much more common to stop using the connection's endpoint's addresses after you've set up the connection. IP address information tends to be unreliable because of the degree to which NAT has been deployed. It is not always wrong to embed IP addresses in your application-level protocol but it is hard to think of examples where it is right.

Fortunately, the alternative is even easier. `self.transport` already represents a certain connection. This is just a regular old Python object. Once you know which two clients are meant to be exchanging data with each other you only need to use the objects to get data sent to the right place.

For example, if you have a server that accepts exactly four connections and a factory which saves a reference to the `IProtocol` provider it creates to handle each of those connections (think about that for a minute: since each `ITransport` provider represents exactly one connection, what must it mean about protocol objects that have a `transport` attribute that refers to one of those? If two protocol objects referred to the same transport... And a single protocol object's `transport` attribute can't possible refer to more than one object...) as attributes `one`, `two`, `three`, `four` then when one of those protocol objects implemented its `dataReceived` method like this:

def dataReceived(self, bytes):
    message = self._parseNewData(bytes)
    if message.complete():
        self.factory.four.transport.write(message.tostring())

This must necessarily be writing data to the fourth connection established to the server. There is no explicit addressing in this example. There is just careful use of certain Python objects.

Careful use of certain Python objects is the overall answer to this question.

Problem

I have written server part using twisted python. Now 4 clients are connected to server which send some data to server. If client 1 sends some data to server then server forwards that data to client 4 and similarly when client 2 sends data to server then server forwards that data to client 3. Thus my problem is that how can I choose particular client on basis of ip address to which I have to send data. In the twisted examples that I have seen to send data to client following code is used ``` self.transport.write("string") ``` How can I specify ip address of client to which I have to send data? My server in tcp server and clients are also tcp(python twisted)

Original source