› Clovertech Forums › Read Only Archives › Cloverleaf › Cloverleaf › Non-persistent TCP/IP
I have a requirement for a non-persistent TCP/IP connection
The scenario is that Cloverleaf is acting as TCP/IP client
When the thread first starts its to delay the connection till a msg is ready – easily enough done via NetConfig
It then sends the message and waits for an ACK
Once the ACK has been received and validated, Cloverleaf should drop the connection
When the next msg comes along the process starts all over again
If I check close after write I never see the ACK
So my question is how do I configure this ?
A suggestion has been to handle the TCP/IP in Tcl – if anyone has some code they’d be prepared to share it would be appreciated
PS The environment is 5.7 on Windows
Cheers,
Bill
Bill,
Are you saying that the receiving system does not send an ack ever?
The scenario you presented indicated they would. if the scenario presented is accurate, I would start by pressuring the receiving system to do what is required.
To handle the ACK, you have the code you need. I believe it is in the contrib directory and Charlie Bursell has posted the latest recover procs on this forum. You need to deploy the recovery procs (either from contrib or from this forum). You may need to modify the proc that actually handles the ACK when it is received (a lot of folks just use hcimsgkill).
On your Outbound Tab click on ‘Await Replies’ and set the timeout you have negotiated with the Receiving system (the default set is -1 that will wait forevever possibly not what you want). Then place the Recover procs (there are more than one of them) in the UPoCs indicated in the procs.
email: jim.kosloskey@jim-kosloskey.com 29+ years Cloverleaf, 59 years IT - old fart.
Jim,
I think he is saying that he has configured cloverleaf to dtop the TCP/IP connection after sending a message, however, it appears that Cloverleaf is dropping the connection before an ACK is received.
Troy
Ironically, I needed to setup this exact scenario today.
Troy and Bill,
I need to get new glasses 😀
Bill – I sent you a proc that may be of some assistance.
email: jim.kosloskey@jim-kosloskey.com 29+ years Cloverleaf, 59 years IT - old fart.
Hi Bill.
I am working on a similar ‘query’ from Cloverleaf. I tried the DRIVER control TCP/IP which, in theory, provides the control we are after .. but this did not work as expected – although this may be a user problem!! Perhaps you can work it properly!
The ‘real’ issue when using a upoc is the delay waiting for a response. When Cloverleaf is using native code, a message is sent and other threads can process while an ACK is being waited on. In a upoc, the ‘wait’ is in the thread, so other processing is stopped – unless its in it own process.
From the Doc (Cloverleaf 5.6)
TCP/IP Command-Line Options
The TCP/IP driver handles three driver control directives. They are passed to it via an outbound message, and are defined in DRIVERCTL in the message metadata. All are boolean.
These directives are:
close
Closes the connection.
reconnect
Reconnects the connection.
writezero
Writes nothing to the connection.
For example:
msgmetaset $mh DRIVERCTL “{TCP/IP {{CLOSE 1} {WRITEZERO 1} }}”
The driver also creates an empty message with close defined if its peer closed the connection.
All,
In today’s environment this must be scripted. Here’s what you want to do if you are using TCP/IP (PDL or non-PDL):
protocol configuration
– configure thread as a client
– turn off “auto reconnect”
– turn off “close after write”
– turn on “delay connection until needed”
– turn on “use DRIVERCTL control”
– turn off “write 0-length messages” (if the option exists)
outbound configuration
– turn on “await replies”
– add custom TPS Inbound Reply proc:
the proc should do the following in RUN mode:
set closeMh [msgcreate]
set dctl “”
keylset dctl CLOSE 1 ;# causes PDL driver to close cxn
keylset dctl TCP/IP.CLOSE 1 ;# causes non-PDL tcp/ip driver to close cxn
msgmetaset $closeMh DRIVERCTL $dctl
lappend dispList “PROTO $closeMh”
lappend dispList “KILLREPLY $mh”
This will cause the driver to send a message, wait for an ACK, and close the connection after the ACK is received. The connection will not be re-opened until there is more data to send.
Hope this helps. FWIW, we are looking at easier ways to do this for future releases. Usual disclaimer about can’t promise anything, but as always, want you to know what we’re thinking about.
— Rob
Rob Abbott
Cloverleaf Emeritus
Thanks Rob.
That worked well – I didn’t find the doco clear enough with respect to the difference between TCP and PDL connections. I had it working for TCP, but not for PDL and the query interface I am connecting to is MLLP.
FYI
I have an inbound XML message.
In the (outbound) prewrite, the message is instantiated with the handle stored globally. The relevant information is extracted and used in a query HL7 template which is loaded into the message handle, so an HL7 query message is communicated outbound.
When an HL7 ACK is received, the ‘close’ message above is generated to close the connection and the HL7 message parsed to get the information which is then loaded into the XML handle and encoded ….
You’re welcome, I’m glad it’s helpful.
I didn’t find the doco clear enough with respect to the difference between TCP and PDL connections.
Agree 100% – in fact after writing this up I put in requests to enhance/clarify the documentation around this; especially the PDL part.
Rob Abbott
Cloverleaf Emeritus
I am trying to get this to work for an outbound thread to a receiving system over tcp/ip. I am running cloverelaf 5.6 on unix.
I can successfully get the thread to close after sending the first message but I don’t appear to be receiving the ACK and the thread will not go up when more messages are waiting to be sent. Using TPS inbound reply to do this.
proc stop_thread_ACK { args } {
keylget args MODE mode
echo “XXXXXXXXargs=$args”
switch -exact — $mode {
start {
# Perform special init functions
# N.B.: there may or may not be a MSGID key in args
echo “START MODE”
}
run {
keylget args MSGID mh
set closeMh [msgcreate]
set dctl “”
keylset dctl CLOSE 1 ;# causes PDL driver to close cxn
keylset dctl TCP/IP.CLOSE 1 ;# causes non-PDL tcp/ip driver to close cxn
msgmetaset $closeMh DRIVERCTL $dctl
lappend dispList “PROTO $closeMh”
lappend dispList “KILLREPLY $mh”
}
}
}
Below is the output from the log file. It is saying that Message sucessfully sent, not awaiting replies. If I disable the TPS inbound reply all messages go through, ACKs are received but threads remain up.
[msg :Msg :DBUG/0: conn_1:04/01/2011 15:01:57] [0.0.1032151] msgFree 0x30001628
[pti :even:DBUG/0: conn_1:04/01/2011 15:01:57] Unregistering TIMER () event 0x20ecd148 for tid 3
[pti :even:DBUG/0: conn_1:04/01/2011 15:01:57] evUnregister TIMER event 0x20ECD148 for tid 3
[diag:leak:DBUG/0: conn_1:04/01/2011 15:01:57] diag dqe free 0x20dcba18
[diag:leak:DBUG/0: conn_1:04/01/2011 15:01:57] diag ev free 0x20ecd148
[tps :tps :INFO/2: conn_1:04/01/2011 15:01:57] [midNULL] Unbind message1 from TPS Interp
[msg :Mid :DBUG/0: conn_1:04/01/2011 15:01:57] mid free [0.0.1032156] 0x20dcf9b8
[msg :Mid :DBUG/0: conn_1:04/01/2011 15:01:57] mid free [0.0.1032156] 0x20dcf768
[pd :thrd:INFO/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Placing msg on OB post-SMS DATA queue
[pd :pdtd:INFO/3: conn_1:04/01/2011 15:01:57] [0.0.1032158] OB post-SMS message details
msg: 0x30002728
msgType : DATA
msgClass : PROTOCOL
msgState : Unknown: 0 (0)
msgPriority : 8193
msgRecoveryDbState: 1
msgFlags : 0x2
msgMid : [0.0.1032158]
msgSrcMid : midNULL
msgSrcMidGroup : midNULL
msgOrigSrcThread : conn_1
msgOrigDestThread :
msgSrcThread : conn_1
msgDestThread :
msgXlateThread :
msgSkipXlate : 0
msgSepChars :
msgNumRetries : 0
msgGroupId : 0
msgDriverControl : {CLOSE 1} {TCP/IP {{CLOSE 1}}}
msgRecordFormat :
msgRoutes :
msgUserData :
msgStaticIsDirty : 1
msgVariableIsDirty: 1
msgTimeStartIb : 1301632317.210
msgTimeStartOb : 1301632317.210
msgTimeCurQueStart: 0.000
msgTimeTotalQue : 0.000
msgTimeRecovery : 1301632317.210
msgEoConfig : 0x0
msgData (BO) : 0x300027d4
message : ”
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has 2 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has SOME work
[pd :thrd:INFO/0: conn_1:04/01/2011 15:01:57] Processing OB-Data message queue
[pd :pdtd:INFO/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Writing message to Protocol Driver tcpip
[tcp :wrte:INFO/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Write msg, length 0
[tcp :wrte:DBUG/2: conn_1:04/01/2011 15:01:57] pdtFlagsCur( pdt ) = 0x3
[tcp :clse:DBUG/1: conn_1:04/01/2011 15:01:57] pdTcpipHandleClose
[pd :pdtd:INFO/1: conn_1:04/01/2011 15:01:57] Set driver status to PD_STATUS_CLOSING
[tcp :clse:INFO/1: conn_1:04/01/2011 15:01:57] Closing client connection
[diag:leak:DBUG/0: conn_1:04/01/2011 15:01:57] diag fd close 25
[pti :even:DBUG/0: conn_1:04/01/2011 15:01:57] Unregistering SOCKET (TCP Client Read) event 0x2167f458 for tid 3
[pti :even:DBUG/0: conn_1:04/01/2011 15:01:57] evUnregister SOCKET event 0x2167F458 for tid 3
[diag:leak:DBUG/0: conn_1:04/01/2011 15:01:57] diag ev free 0x2167f458
[pd :pdtd:INFO/1: conn_1:04/01/2011 15:01:57] Set driver status to PD_STATUS_DOWN
[tcp :clse:DBUG/1: conn_1:04/01/2011 15:01:57] pdTcpipHandleClose done
[pd :pdtd:INFO/1: conn_1:04/01/2011 15:01:57] [0.0.1032158] Writing message succeeded
[pd :pdtd:INFO/1: conn_1:04/01/2011 15:01:57] [0.0.1032158] Latencies: Outbound 0.006, Que 0.000, Total 0.006 secs
[pd :pdtd:INFO/2: conn_1:04/01/2011 15:01:57] [0.0.1032158] Writing msg to outbound save file conn_1_out
[pd :thrd:INFO/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Invoking SENDOK
[pd :thrd:DBUG/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Message successfully sent, not awaiting replies. Removing msg from db.
[dbi :rlog:DBUG/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] Msg not removed from rdb; state=1
[msg :Msg :DBUG/0: conn_1:04/01/2011 15:01:57] [0.0.1032158] msgFree 0x30002728
[pti :sche:INFO/1: conn_1:04/01/2011 15:01:57] Thread has 0 ready events left.
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has NO work
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has NO work
[tcp :read:ERR /0: conn_2:04/01/2011 15:01:57] Read 0 bytes — peer disconnected?
[tcp :read:ERR /0: conn_2:04/01/2011 15:01:57] Unable to read msg length
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:57] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:57] msiExportStats: export for thread: conn_1
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:57] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:57] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:57] msiExportStats: export for thread: conn_1
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Receiving a command
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Receiving a command
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Received command: ‘healthtrack_req_xlate xrel_post’
[cmd :cmd :INFO/0:healthtrack_req_xlate:04/01/2011 15:01:58] Doing ‘xrel_post’ command with args ”
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Receiving a command
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Command client went away. Closing connection.
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:58] Receiving a command
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:58] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:58] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:58] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:59] Receiving a command
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:59] Received command: ”healthtrack_req_xlate’
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:59] Cmd null in ”healthtrack_req_xlate’
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:59] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:59] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:59] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:59] msiExportStats: export for thread: conn_1
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:59] Receiving a command
[cmd :cmd :INFO/0:healthtrack_req_cmd:04/01/2011 15:01:59] Command client went away. Closing connection.
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:59] OB-Data queue has 1 msgs
[pd :thrd:INFO/1: conn_1:04/01/2011 15:01:59] OB-Data queue has NO work
[pti :sche:INFO/2: conn_1:04/01/2011 15:01:59] Performing apply callback for thread 3
[msi :msi :DBUG/1: conn_1:04/01/2011 15:01:59] msiExportStats: export for thread: conn_1
Hi Rob,
I have come up with a need for your code, which works great by the way. Thanks!!!! My one concern is, I’m on 5.7 with the new OBMSGID. In the proc that you create the dctl, do I need to grab the OBMSGID and kill it also?
Thanks,
John Mercogliano
Sentara Healthcare
Hampton Roads, VA