How to handle a TCP/IP Response without terminator character using EnsLib.TCP.TextLineOutboundAdapter
Hello everyone,
I'm using EnsLib.TCP.TextLineOutboundAdapter to communicate with a third-party system over TCP/IP. The issue is that the system sends back only an integer (e.g. 1001 or -1) without any terminator (like $c(10)).
The adapter expects a terminator and always times out with ErrTCPTerminatedReadTimeoutExpired, even though the correct data is received. Here an example of an error:
[TCPSender] Errore nell'invio: ERROR <Ens>ErrTCPTerminatedReadTimeoutExpired: TCP Read timeout (15) expired waiting for terminator 0, data received ='1005'
Trying different terminators (e.g. $c(0), $c(13))didn’t work.
I’d like to know if there’s a way to disable terminator checking or manually read the entire response without waiting for an end character.
Thanks in advance!
Enrico
Comments
To address the behavior of the EnsLib.TCP.TextLineOutboundAdapter, where it expects a terminator and times out if none is provided, you have a few options:
Explicitly Set a Terminator: You can set the
Terminatorproperty of your adapter to a character or sequence of characters that you might expect (though you already attempted$c(10)or$c(13)without success). According to the documentation, this property supports multi-character strings [1].Example of code customization:
Class Custom.TCPAdapter Extends EnsLib.TCP.TextLineOutboundAdapter { Property Terminators As %String [ InitialExpression = "" ]; // Clear terminators if none should apply }Custom Adapter or Manual Reading Logic: If the responses truly do not include terminators and cannot be adjusted on the third-party side, you might need to implement your own logic for receiving data. This involves overriding the necessary methods in the adapter to change how responses are interpreted — possibly using a timeout or a custom data parse handler to disconnect terminator reliance.
Example of using a manual read logic:
Method ReadWithoutTerminator() { // Example of binary mode read without terminators set device = "|TCP|Host:Port" open device:("R") use device read x:Timeout quit x }Binary Stream Mode: You could configure the adapter to operate in binary mode (
/IOT="RAW"). Manually process the data reading and assembly based on expected response patterns or sizes [2][3].Example:
set device="|TCP|7000" open device:(host:port:"M") use device:(/IOT="RAW") read response:Timeout
You should consider adapting the built-in EnsLib.TCP.TextLineOutboundAdapter or creating a subclass of it for better control over edge-case behaviors. [4][2][3]
Sources:
I wonder how you expect to know that your input is complete without any terminator.
And according to your example, you also don't have a fixed length:
Withoit an clear signal timeout seems to be the only way to know you are complete.
You may read input character by character without guarantee
how do decide for 1 or 10 or 100 or 1000 ?
Some ending character (eg. not numeric) or a fixed length is required
you could try to set your terminator to null String "".
it is optional accordig to docs
https://docs.intersystems.com/iris20251/csp/docbook/DocBook.UI.Page.cls?KEY=GIOD_tcp#GIOD_tcp_open
- terminators
Optional — A list of up to eight user terminator characters that will terminate reads on the TCP binding device. If you specify both T mode and terminators at the same time, T mode is ignored.