Thanks Rory and Scott.
I have been reading (and re-reading) the Time-outs with Sockets article,
and have found it very helpful. I've incorporated all the select() and
non-blocking procedures, and I think that will work for me. Much
testing to do yet, and I may have more questions before I get to a
production-ready product.

Won't be back in until Monday, but many thanks for getting me on track
here.

Michael


-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of Scott Klement
Sent: Wednesday, March 02, 2011 7:48 PM
To: RPG programming on the IBM i / System i
Subject: Re: Socket Recv Question

Michael,

If you are in blocking mode (the default) and you call the recv() API,
the system won't return control back to your program until there's data
to return. This is referred to as "blocking." The term "blocking"
essentially means that the OS has stopped execution of your program,
waiting for some event to occur.

If you put the socket in non-blocking mode, it won't ever wait. If
there's data available at the instant when you call recv(), you'll get
it. If there isn't any data, you'll get back control immediately, but
recv() will return <1, and errno=EWOULDBLOCK. (Or, EAGAIN, which means
the same thing.)

If you want to call recv() and have it wait for data, but time-out after

a period of time if no data arrives, then you might appreciate this
article:
http://systeminetwork.com/article/timeouts-sockets-0

For the type of application you're writing, you might consider
refactoring it into an event-driven model. The main loop would look
somethhing like this:

socket()
connect()

dow connected;
FD_ZERO(readset);
FD_ZERO(writeset);
FD_SET(mysock: readset);
if (theres_data_to_write);
FD_SET(mysock: writeset);
endif;
n = select( mysock+1
: %addr(readset)
: %addr(writeset)
: *null
: *null );
if (n < 1);
// handle error
endif;
if FD_ISSET(mysock: readset);
recv();
// if error, set connected=0
call program_logic();
endif;
if FD_ISSET(mysock: writeset);
send();
// if error, set connected=0
endif;
enddo;

The idea is that your program is constantly trying to send/receive data
from the host. When your main program logic has data to send, it puts it

in the send buffer, and the main loop takes care of the actual sending.

When data is received, your main loop receives the data into a buffer.
Then calls your program's logic.

What I mean by "event driven" is that your program logic is only called
when something happens. (As coded above, it'd only be called when new
data appears on the wire. But you could easily change this to have it
called on a particular time interval even if no data is received.)

Your code would be designed to do whatever it needs to do without
stopping, and then return control back to the main loop. Maybe you scan
for the string you're looking for... and if found, process it... but
then go back to the main loop. You never get hung up waiting for data,
you just look for data you need, and if it's not there, you go back to
waiting.

Not sure if that fits your scenario or not, but sounds like it would.
Aside from a scenario like this, I can't think of any situation where
you wouldn't know when your "command" is finished!


On 3/2/2011 3:54 PM, Koester, Michael wrote:
Don't know if this is related, but I also am having trouble with
recv().
Since I don't know when I've received everything that will be sent
(from
telephone switch equipment), if I don't find the expected string in
the
buffer, I save what I've received so far and call recv() again. This
seems to work to get additional data when I'm trying to check results
too soon, but I suspect when there's nothing more to be sent (how
would
I know?), and I call recv() again, control does not return to my RPG
program.
Has recv() timed out? I have to crash the job, which leaves a
connection to the switch open and messes to clean up.
I haven't done anything fancy with recv(). The line that locks up is:

rc = recv(sock: %addr(recbuf):3000:0);

I send the request to the switch with "send(sock: %addr(request):
reqlen:0)", and then execute a dou loop to interpret the response from
the switch:
Dou done;
[wait a bit]
Recbuf = *blanks;
rc = recv(sock: %addr(recbuf):3000:0);
[translate recbuf to EBCDIC and scan for expected prompt
string]
[If found, leave do loop - else, repeat loop up to a
reasonable number of times]
Enddo;

Debug confirms that it hangs on recv(). Works well so long as the
expected prompt is returned, but I can't process the "not found"
condition if I don't know that there isn't more to receive...

Suggestions welcome!
Michael

-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of Scott Klement
Sent: Wednesday, February 23, 2011 3:50 PM
To: RPG programming on the IBM i / System i
Subject: Re: Socket Recv Question

Have you disabled Nagle's algorithm? That may be throwing off your
benchmarks.

On 2/23/2011 2:31 PM, Zachary Johnson wrote:

Hi Scott, thanks for the reply. Yes, using SOCK_STREAM. I still
think it's odd though that the short request would take longer to
arrive on the socket than the large request. It's driving me up the
wall that I have no other explanation other than "that's how it
works". Thanks again for the response.



As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.