6

Is there any way to force self.transport.write(response) to write immediately to its connection so that the next call to self.transport.write(response) does not get buffered into the same call.

We have a client with legacy software we cannot amend, that reads for the 1st request and then starts reading again, and the problem I have is twisted joins the two writes together which breaks the client any ideas i have tried looking into deferreds but i don't think it will help in this case

Example:

self.transport.write("|123|") # amount of messages to follow 
a loop to generate next message
self.transport.write("|message 1 text here|")

Expected:

|123|
|message 1 text here|

Result:

|123||message 1 text here|
Glyph
  • 31,152
  • 11
  • 87
  • 129
Jarratt
  • 168
  • 1
  • 6
  • Hi, i know this is a old post but can you tell me what did you do to solve this problem? – Gaurav_soni Apr 09 '12 at 06:24
  • For what it's worth, it's impossible to make this work completely reliably. One day you might buy some different switch or routing hardware and your application will break. This Twisted FAQ attempts to explain: http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#Whyisprotocol.dataReceivedcalledwithonlypartofthedataIcalledtransport.writewith – Glyph Jul 22 '13 at 21:33

3 Answers3

2

I was having a somewhat related problem using down level Python 2.6. The host I was talking to was expecting a single ACK character, and THEN a separate data buffer, and they all came at once. On top of this, it was a TLS connection. However, if you reference the socket DIRECTLY, you can invoke a sendall() as:

self.transport.write(Global.ACK)

to:

self.transport.getHandle().sendall(Global.ACK)

... and that should work. This does not seem to be a problem on Python 2.7 with Twisted on X86, just Python 2.6 on a SHEEVAPlug ARM processor.

0

Can you tell which transport you are using. For most implementations, This is the typical approach :

 def write(self, data):
        if data:
            if self.writeInProgress:
                self.outQueue.append(data)
            else:
                ....

Based on the details the behavior of write function can be changed to do as desired.

pyfunc
  • 65,343
  • 15
  • 148
  • 136
0

Maybe You can register your protocol as a pull producer to the transport

self.transport.registerProducer(self, False)

and then create a write method in your protocol that has it's job buffering the data until the transport call your protocol resumeProducing method to fetch the data one by one.

def write(self, data):
    self._buffers.append(data)

def resumeProducing(self):
    data = self._buffers.pop()
    self.transport.write(data)
Harianja Lundu
  • 137
  • 1
  • 7