As Jean-Paul says, you should use IProducer and IConsumer, but you should also note that the lack of deferredWrite
is a somewhat intentional omission.
For one thing, creating a Deferred
for potentially every byte of data that gets written is a performance problem: we tried it in the web2
project and found that it was the most significant performance issue with the whole system, and we are trying to avoid that mistake as we backport web2
code to twisted.web
.
More importantly, however, having a Deferred
which gets returned when the write
"completes" would provide a misleading impression: that the other end of the wire has received the data that you've sent. There's no reasonable way to discern this. Proxies, smart routers, application bugs and all manner of network contrivances can conspire to fool you into thinking that your data has actually arrived on the other end of the connection, even if it never gets processed. If you need to know that the other end has processed your data, make sure that your application protocol has an acknowledgement message that is only transmitted after the data has been received and processed.
The main reason to use producers and consumers in this kind of code is to avoid allocating memory in the first place. If your code really does read all of the data that it's going to write to its peer into a giant string in memory first (data_block = get_lots_and_lots_data()
pretty directly implies that) then you won't lose much by doing transport.write(data_block)
. The transport will wake up and send a chunk of data as often as it can. Plus, you can simply do transport.write(hugeString)
and then transport.loseConnection()
, and the transport won't actually disconnect until either all of the data has been sent or the connection is otherwise interrupted. (Again: if you don't wait for an acknowledgement, you won't know if the data got there. But if you just want to dump some bytes into the socket and forget about it, this works okay.)
If get_lots_and_lots_data()
is actually reading a file, you can use the included FileSender class. If it's something which is sort of like a file but not exactly, the implementation of FileSender might be a useful example.