EmbeddedRelated.com
Forums

RCM3000 to "Progress 4GL" Server delay on TCP/IP socket writes

Started by mario_wtbbh April 29, 2011
I was hoping that someone could shed some light on the TCP/IP "nuts and
bolts" for the RCM3000. We've had lots of trouble-free experience with
listening sockets and active writing/reading sockets to/from a multitude
of different server platforms, but last week this problem really stumped
me.

My Dynamic C (9.52) program, stripped to basics, opens an ASCII socket,
writes one or more simple ASCII strings and closes the socket.

All writes + close return "instantly" with no errors. Nothing appears on
the Server window for at least 5 seconds, then "presto", all at once.

The server was written in the "Progress 4GL" environment. Our customer
stripped his code down to ultra-basic, "listen", "onRead", "show
output".

We also tried my simple server/client written in VC++ (MFC) using
CASynchSockets. Here are the results:
(MFC server run on SAME PC, SAME Network as Progress Server (Progress
Server shut down))

RCM3000 >> Progress: 5-10 sec lag AFTER sock_close, then all appear.
Progress >> RCM3000: Instant

RCM3000 >> MFC: Instant
MFC >> RCM3000: Instant

MFC >> Progress: Instant
Progress >> MCF: Instant

I've tried sock_write, sock_puts, Nagle/NoNagle, ASCII/binary modes.

It's as if Progress was waiting for some concluding handshake, or a data
timeout.
You would think that closing the socket would finalise any pending
handshake?

Here's the basic "sending" function and "close" function:

int TCPSendMessage(tcp_Socket *pSock, char *szOut)
{
auto int result;

if(tcp_tick(pSock))
{
sock_flushnext(pSock);

// Tried one or the other
//result = sock_write(pSock, szOut, strlen(szOut));
result = sock_puts(pSock, szOut);

sock_flush(pSock); // Tried with and without extra flush
tcp_tick(NULL);
}
else
return -2;

if(result < 0)
return -1;

return (result);
}
xmem void CloseSocket(tcp_Socket *pSkt, BOOL bWait)
{
auto unsigned long Start;

sock_close(pSkt);

if(bWait)
for(Start = MS_TIMER; MS_TIMER - Start < 5000; ) // Never times out;
always closes "instantly"
if(tcp_tick(pSkt) == 0)
break;

if(tcp_tick(pSkt))
sock_abort(pSkt);
}
Have you tried using Wireshark to look at the comms in detail? You will need to use a hub, a network tap or a managed switch with port mirroring to see the RCM3000 comms (unless you can run it on the server). With this you can at least compare the different systems "on the wire" and see if there is an obvious difference in the sequences.

Regards.
Peter

--- In r..., "mario_wtbbh" wrote:
> I was hoping that someone could shed some light on the TCP/IP "nuts and
> bolts" for the RCM3000. We've had lots of trouble-free experience with
> listening sockets and active writing/reading sockets to/from a multitude
> of different server platforms, but last week this problem really stumped
> me.
>
> My Dynamic C (9.52) program, stripped to basics, opens an ASCII socket,
> writes one or more simple ASCII strings and closes the socket.
>
> All writes + close return "instantly" with no errors. Nothing appears on
> the Server window for at least 5 seconds, then "presto", all at once.
>
> The server was written in the "Progress 4GL" environment. Our customer
> stripped his code down to ultra-basic, "listen", "onRead", "show
> output".
>
> We also tried my simple server/client written in VC++ (MFC) using
> CASynchSockets. Here are the results:
> (MFC server run on SAME PC, SAME Network as Progress Server (Progress
> Server shut down))
>
> RCM3000 >> Progress: 5-10 sec lag AFTER sock_close, then all appear.
> Progress >> RCM3000: Instant
>
> RCM3000 >> MFC: Instant
> MFC >> RCM3000: Instant
>
> MFC >> Progress: Instant
> Progress >> MCF: Instant
>
> I've tried sock_write, sock_puts, Nagle/NoNagle, ASCII/binary modes.
>
> It's as if Progress was waiting for some concluding handshake, or a data
> timeout.
> You would think that closing the socket would finalise any pending
> handshake?
>
> Here's the basic "sending" function and "close" function:
>
> int TCPSendMessage(tcp_Socket *pSock, char *szOut)
> {
> auto int result;
>
> if(tcp_tick(pSock))
> {
> sock_flushnext(pSock);
>
> // Tried one or the other
> //result = sock_write(pSock, szOut, strlen(szOut));
> result = sock_puts(pSock, szOut);
>
> sock_flush(pSock); // Tried with and without extra flush
> tcp_tick(NULL);
> }
> else
> return -2;
>
> if(result < 0)
> return -1;
>
> return (result);
> }
> xmem void CloseSocket(tcp_Socket *pSkt, BOOL bWait)
> {
> auto unsigned long Start;
>
> sock_close(pSkt);
>
> if(bWait)
> for(Start = MS_TIMER; MS_TIMER - Start < 5000; ) // Never times out;
> always closes "instantly"
> if(tcp_tick(pSkt) == 0)
> break;
>
> if(tcp_tick(pSkt))
> sock_abort(pSkt);
> }
>

Thanks Peter,

That was going to be my next move when I return to site in about a week.

In the meantime, I think I found one clue. See Message #31065 (back from
2006), "Re: Odd TCP behavior".
That problem was related to excessive retransmissions, but there was
this note:

"The initial rto value seems to come from the timing of SYN per the
comments starting on line 3203 of tcp.lib. I commented out lines 3207,
3208, and 3209 to stop the timing of the SYN segment as the initial
rto value & I no longer get retransmits. The first data packet gets
the default rto value of 6000ms, which doesn't cause a timeout. It
then drops to about 400ms for the second packet once the valid rto is
found."

That "default rto of 6000 ms" sounds exactly like the lag I am
observing.
Note this was using DC 9.25 - I'm still to check for the equivalent code
in DC 9.52 (my version).

Also note that my problem does appear to do with timeouts determined
with the initial negotiation: For one test, I pulled the cable as soon
as my debug printed "all sent". The data still appeared on the server
after the usual 6s lag, so the server stack had all the data ... it was
just waiting to see if it should pass it "up the chain" yet.

Regards,

Mario
--- In r..., "petermcs" wrote:
>
> Have you tried using Wireshark to look at the comms in detail? You
will need to use a hub, a network tap or a managed switch with port
mirroring to see the RCM3000 comms (unless you can run it on the
server). With this you can at least compare the different systems "on
the wire" and see if there is an obvious difference in the sequences.
>
> Regards.
> Peter
>
> --- In r..., "mario_wtbbh" m.galea@ wrote:
> >
> >
> > I was hoping that someone could shed some light on the TCP/IP "nuts
and
> > bolts" for the RCM3000. We've had lots of trouble-free experience
with
> > listening sockets and active writing/reading sockets to/from a
multitude
> > of different server platforms, but last week this problem really
stumped
> > me.
> >
> > My Dynamic C (9.52) program, stripped to basics, opens an ASCII
socket,
> > writes one or more simple ASCII strings and closes the socket.
> >
> > All writes + close return "instantly" with no errors. Nothing
appears on
> > the Server window for at least 5 seconds, then "presto", all at
once.
> >
> > The server was written in the "Progress 4GL" environment. Our
customer
> > stripped his code down to ultra-basic, "listen", "onRead", "show
> > output".
> >
> > We also tried my simple server/client written in VC++ (MFC) using
> > CASynchSockets. Here are the results:
> > (MFC server run on SAME PC, SAME Network as Progress Server
(Progress
> > Server shut down))
> >
> > RCM3000 >> Progress: 5-10 sec lag AFTER sock_close, then all appear.
> > Progress >> RCM3000: Instant
> >
> > RCM3000 >> MFC: Instant
> > MFC >> RCM3000: Instant
> >
> > MFC >> Progress: Instant
> > Progress >> MCF: Instant
> >
> > I've tried sock_write, sock_puts, Nagle/NoNagle, ASCII/binary modes.
> >
> > It's as if Progress was waiting for some concluding handshake, or a
data
> > timeout.
> > You would think that closing the socket would finalise any pending
> > handshake?
> >
> > Here's the basic "sending" function and "close" function:
> >
> > int TCPSendMessage(tcp_Socket *pSock, char *szOut)
> > {
> > auto int result;
> >
> > if(tcp_tick(pSock))
> > {
> > sock_flushnext(pSock);
> >
> > // Tried one or the other
> > //result = sock_write(pSock, szOut, strlen(szOut));
> > result = sock_puts(pSock, szOut);
> >
> > sock_flush(pSock); // Tried with and without extra flush
> > tcp_tick(NULL);
> > }
> > else
> > return -2;
> >
> > if(result < 0)
> > return -1;
> >
> > return (result);
> > }
> >
> >
> > xmem void CloseSocket(tcp_Socket *pSkt, BOOL bWait)
> > {
> > auto unsigned long Start;
> >
> > sock_close(pSkt);
> >
> > if(bWait)
> > for(Start = MS_TIMER; MS_TIMER - Start < 5000; ) // Never times out;
> > always closes "instantly"
> > if(tcp_tick(pSkt) == 0)
> > break;
> >
> > if(tcp_tick(pSkt))
> > sock_abort(pSkt);
> > }
>