CSI TCP/IP Socket Send Techniques

New Message Reply Date view Thread view Subject view Author view Other groups

Subject: CSI TCP/IP Socket Send Techniques
From: Don Stoever (don@e-vse.com)
Date: Tue Aug 19 2008 - 10:38:44 EDT


Hello vse-L friends, 

I have returned from a sabbatical (rode Harley Road King from Columbus,OH. to
Sturgis,SD and back), 
and after reviewing some of the postings from the:
"RE: SOCKET RECEIVE techniques..." thread
I have decided to start a new thread and change the title from:
"RE: SOCKET RECEIVE techniques..."
to:
"CSI TCP/IP Socket Send Techniques",
and add some actual send techniques for sending data.

The assembler SOCKET macro is the lowest level api that we provide,
and allows the assembler based applications the flexibility to send
data with or without waiting for sent data to be acknowledged by the
foreign stack.

The SEND operation can transmit chunks of data of almost any size.  The
data will be queued and carved-up into proper sized chunks to send over
the network.

There are several techiques for maximizing throughput.  The first is for the
application to reasonably buffer its data.  Issuing lots of small SENDs because
"it's easier" is not the mark of a good programmer.  In addition to increasing
the amount of time required to transfer data, such technique adds unnecessary
overhead, and consumes more CPU cycles.

For those wishing to code highly-efficient, fast transports, it is necessary to
include use of the "FAST" option of the SOCKET macro.  Simply, coding "FAST"
tells the stack to queue the operation but NOT to inform the application when
it completes.

This puts some additional demands on the application, both in the detection and
recovery of errors, as well as not to "flood" the stack with data.

These recommenedations would be for a appliction that is
primarily sending out a large amount of data in multiple send requests
without a application receive before each send request.
For applications that issue a send followed by a receive
I would recommend using the simple send then wait for the ecb to be posted
(at least you then know in your application that the data has been received
by the foreign stack). Your application can then issue it's receive.

But when sending large amounts of data from VSE consider one of the
following techniques for customer or vendor applications:

1) Use the socket macro with 2 send buffers with separate result
areas(SRBLOK's).
The first fullword of the SRBLOK contains the ecb that can optionally be waited
on to verify the sent data has been ack'ed by the corresponding foreign stack.
Let's call them sendbufA and sendbufB. Fill sendbufA and send it out without
waiting, and continue to fill sendbufB. When sendbufB is full and ready to send
immediately send it, and then wait on sendbufA's ecb.
Using this simple method of buffer overlapping should keep enough data queued to
the foreign stack, and minimize delays without having to worry about tcp window
closing or excessive storage usage. You could also design and modify this
technique for using 3 or 4 overlapping send buffers.

2) Use the socket macro with fast=yes to send out data.
You must check R15 after issuing this call and if it is zero then all the data
will have been copied to the TCP/IP partition.
The SRBLOK and data buffer can then immediately be reused for the next
send request with fast=yes.
The data will be parsed and sent out in datagrams(ibbk's) by the TCP/IP
partition.
When the application terminates it should issue a close with fast=no, and wait
for the close to complete.
The close will generate a final datagram with a FIN setting, so if the close
successfully completes your application will then at least know that all the
sent data has made it through the network and been acknowledged by the foreign
stack. Which, I would think is a good thing.
Would you really want to send out data and have the job step terminate with a
zero return code,
and the data has not even arrived/been acknowledged by the foreign connection?
Your application could also issue the close with fast=yes, and the fin will be
sent, with no wait in your application.
I would not recommend doing this though since it leaves a large question about
the other stack actually successfully receiving the sent data.
I would only recommend this if the foreign application is designed to send some
sort of final I got your sent data, and the application on VSE ends with a final
receive for this final application level acknowledgment that the data was
received.
The FTP protocol with it's final "226 TRANSFER FINISHED SUCCESSFULLY" is an
example of a application that sends out a final message when all of the data has
been successfully transferred.

3) This is really a slight modification of option 2 above.
This is more or less the technique used in our BSD/C socket interface.
Issue a socket status call before issuing each send(or on every other send
request).
The returned connection status block(STBLOK) contains 2 double word fields:
STSQSEQ         Next seq to be sent
STSUNACK        Next unacked seq no.
STSQSEQ - STSUNACK = the number of bytes sent but not acknowledged by the
foreign stack.
You could set a arbitrary value of 512k or more and slow down your application
send by issuing a send with a wait to allow the network to digest/get caught up
with the un'acked data.
Or issue a timer then reissue the status and resume send with fast=yes when the
unack'ed count gets below 256k(or any other selected value).
Then once the un'acked count is acceptable continue the sends with fast=yes.

4) Use the BSD/C API and $SOCKOPT.phase sockopt settings to control sending of
data.
The name(BSD/C) seems to indicate that this api can only be called from C
applications,
but it can be called from any language that has standard call/save linkage,
including Assembler, Cobol, PL/1, etc.
More accurately it could be called the Basic Socket API.
Historically it is the defacto standard for coding TCP/IP applications.
It's concepts for server's using bind, listen and accept for establishing new
connections, and clients using connect is widely published, but not in any
official RFC
for IPv4 that I am aware of.
The IPv6 RFC3493 titled "Basic Socket Interface Extensions for IPv6" contains
the following introduction:
   The de facto standard Application Program Interface (API) for TCP/IP
   applications is the "sockets" interface.  Although this API was
   developed for Unix in the early 1980s it has also been implemented on
   a wide variety of non-Unix systems.  TCP/IP applications written
   using the sockets API have in the past enjoyed a high degree of
   portability...
This RFC does contain a good and official definition for the
BSD API functions, but is directed to IPv6.

Well, I think that is enough to chew on for now.
Hope it helps.
Don Stoever
CSI TCP/IP Product Developer


New Message Reply Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b25 : Tue Aug 19 2008 - 17:50:13 EDT