I have a general question about what is possible in the realm of sockets when communicating with a CICS mainframe.
We have a piece of middleware software that collects and consolidates data from various sources and then passes that data on to various external systems such as ODBC databases, etc. We have provided a generic XML protocol over a TCP/IP socket connection to allow flexible connections to any backend host computers. The problem we are now hitting is a client who claims our topology/protocol isn't possible for them to handle in their environment.
Here is our system in a nutshell: We open a socket connection to the remote port and send what amounts to a logon message. Assuming we receive a favorable response we then send data messages up, each of which has a response that can contain error information or possible result from the remote processing. If a specified amount of idle time elapses between these data messages, we send a kind of keep-alive message that again has a response. Finally, when the overall processing is complete send the equivalent of a logoff message.
A few additional details: Because our software has no guarantee of how fast the host program will process any individual data message, we support a small fixed number of simultaneous connections so that long-running tasks won't totally block other shorter-running ones. The volume of these data messages varies from many-per-second to periods where minutes (or even perhaps hours) can go by without any new data. This approach works fine for the likes of a Java program running on a Unix box, but does it really present such a problem in the CICS world?
Continued from part I.
The second service transaction is where all the work is done. Again, you are going to have to be careful about how you obtain variable length messages -- and what are you going to do if a bit of the next one arrives along with the current. I assume that you can detect this as you are using an XML-type of formatting (find something after the and you have got something else to do). This second transaction is running under the security identity passed in via the initial flow, which is why you have got two service transactions.
This second service transaction is more complex than the other two. The degree of complexity depends on wheher or not two distinct flows can be available at the same time. If this is true, then you have got to be able to recognise the end of one request and the start of another (so that you can process one and save the other for subsequent use). However, I'm assuming from your description that the logon message and the action message can flow together, but a second action message will not arrive until the previous one has been processed.
You might also want to do something with SELECT() to see if the socket is read to accept a flow from CICS.
The IOCTL call must be made to set the socket communication to be non-blocking (asynchronous operation), and you should do a GETSOCKOPT to determine the maximum length of a flow that can be sent from CICS is one go. I'm going to assume for simplicity that the reply does not have to be broken up into bits.
The arrival of the next request is indeterminate, although it can be a request or an heartbeat. It is this interval and consequent use of CICS resources that will cause you the most trouble. Thus, you have a case statement to decide whether to do something or ignore it (the heartbeat).
So, the second transaction looks like:
INITAPI(); XC RETRIEVE; TAKESOCKET(); IOCTL(NonBlocking); GETSOCKOPT(SNDBUF)
Loop to get all of request flow: RECV(Peek); XC GETMAIN; RECV (into the getmained area); reloop until RECV(PEEK) is zero; endloop. Add up the lengths of data passed in the start data and all the RECV()ed areas. Getmain a new area and copy everything. XC FREEMAIN the areas used for the incoming TCP/IP flow. Select upon what is to be done (see below).
Action: Do the requested operation (which is running under the user-based security identity) XC GETMAIN the output buffer and fill it up; SEND(); SELECT(); XC FREEMAIN the input and output buffers.
Heartbeat: Do nothing (or maybe count them up to a limit which when exceeded CLOSE()s and XC RETURNs)
End of flow received: Stop by CLOSE()ING and XC RETURNing
TCP/IP timeout: Stop by CLOSE()ing the socket and XC RETURNing
At this point you have finished processing the request sent in from the client, and have to hang around for the next event to occur. This can be another request or a heartbeat (or a timeout). In the data cases you want to go back to the receive loop.
Dig Deeper on IBM system z and mainframe systems
Related Q&A from Robert Crawford
For better mainframe capacity planning, how do I convert CPU hours to MIPS? And is there a way to calculate the relationship between MIPS and MSUs? Continue Reading
I have two years of experience in mainframe technology, currently working as a mainframe developer. I want to change to Java technology. Continue Reading
I want to replicate DB2 from the mainframe to an AIX box since it's cheaper and the copy can be used for testing. Is this possible? Continue Reading
Have a question for an expert?
Please add a title for your question
Get answers from a TechTarget expert on whatever's puzzling you.