× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Hi Scott,

Thanks for your reply... I was just using the GetReply() from the CLIENT1 sample program.
I'm no longer using the GetReply().

Please forgive me if I'm sometimes a little slow in "getting there" to understand how this works.
It helped when I finally figured out how to get into the routine in debug (F15 and listing view).
I hope you can guide me a little more in the right direction because I fear I'm spinning wheels again.

I suppose I'm still having a problem understanding what I need to re-write and how I need to re-write it,
I've read and re-read the article, and then I read the specs provided by the vendor and I'm having trouble putting them together.

I'm wondering if I also need to address the code for the connect, although I am getting a valid response.

When I try to do a connect() a value comes back for my "s" value in this statement:
if ( connect(s: %addr(connto): %size(connto)) = -1 );

Does the fact that I get an integer rather than -1 mean that I DID get a connection?
It's hard to tell when I can't see a reply, and my attempts to get a reply have failed so far.

My questions are...

1.) Regarding the connect:

My specs from the vendor say that, in order to connect, I need to run a CONNECT API which they describe in their manuals.
I'm not sure if the is the same as the point where I do the connect() command (the above if statement) or if this is even the same thing... They sure don't look the same. Or do I need to do a connect() in RPG and then, once I'm connected to the server through the RPG program, send their CONNECT data to their CONNECT API.
It seems odd that I have to connect() so that I can CONNECT.

For their connect, the documentation expects me to send this to their server:

'0000000035CONNECT|CLIENTTYPE|10|CLIENTID|123|'

It's supposed to send back

0000000003OK|
Or
0000000005FAIL|


Where 000035 is the number of characters and the 123 is the name of the server. There are a few other optional fields.

My question: Is that string something that I need to set up in the data structure going into connect()?

You did say in the "Introduction to TCP/IP Programming" that data structure in the sample (connto), a likeds to sockaddr_in
And you said that "There are different socket address data structures for different network protocols."

I'm wondering if that means that I need to create a new data structure that somehow includes that string of data...

Sockaddr_in looks like this:

D sockaddr_in DS based(p_sockaddr)
D sin_Family 5I 0
D sin_Port 5U 0
D sin_addr 10U 0
D sin_zero 8A

So do I need a new data structure that also contains a field with that string starting with the '0000000035CONNECT|

OR

Do I need to do the connect() and THEN do a SendAscii with the string starting '0000000035CONNECT|...

(OR is there some third other "OR" possibility that I'm missing because I'm not understanding something?)

The latter is how I coded it.

It's just confusing to me that I would do a connect() in RPG to connect to the server, and then do their command 0000000035CONNECT to connect to the server.

If it's all in one connect, then how/where do I put the ...00035CONNECT string into the connect() data structure?

Or was the latter correct?

2.) Regarding the receive reply.

Since I AM getting an integer with the connect(), may be I was correct with my connect logic and I have a problem with the send().
Again, I'm not sure how to re-code it.

As I started examining this, I realized that I had already started re-writing it about a year ago and got stopped. (Project priorities shifted... I'm back on a project I worked on back around the end of 2009.) I don't remember how I got to this point, but I started working with what I had before so here's what I have now...

I'm trying to write the procedure so that, after I do the SendAscii that would receive data back and convert it back to EBCDIC from ASCII, sort of the opposite of SendAscii... RecvAscii.

Below is the main program (from connect to RecvAscii) and the beginning of the prototype RecvAscii.

It's getting a -1 on RecLen = recv(s: RspBufAdr : RspBufLen : 0);

Another thing... The RecvAscii hit the line to Return -1, but when I come back to the program the s value is not -1!

Thanks for any guidance you can give me!

Charlie

//*---------------------------------------------------
// 3. Connect to server.
//*---------------------------------------------------

connto = *ALLx'00';
connto.sin_family = AF_INET;
connto.sin_addr = addr;
connto.sin_port = port;

// If error in connect.

if ( connect(s: %addr(connto): %size(connto)) = -1 );
callp close(s);
@preturn = 'CPCON03';
@prtnmsg = 'Connect failed. ';
joblog('Connect failed!');
return;

endif;

//*---------------------------------------------------
// 4. Purolator CONNECT API Command.
//*---------------------------------------------------

SendAscii(s:
'0000000035CONNECT|CLIENTTYPE|10|CLIENTID|123|');

//*---------------------------------------------------
// 5. Recieve Purolator Reply.
//*---------------------------------------------------

RecvAscii(s: data);


//*---------------------------------------------------




d RecvAscii pr 10I 0
d sock1 10I 0 value
d data1 1024A value


P RecvAscii B

d RecvAscii pi 10I 0
d sock 10I 0 value
d data 1024A value

d RecLen s 10I 0
d s s 10I 0
d RspBufAdr s *
d RspBufLen s 10I 0
D reply s 10I 0

/free
// ---------------------------------------------------
// Execute the Recv() API to get the ESS response
// and translate the ASCII to EBCDIC
// ---------------------------------------------------

// Recv() API parameters
// int - Socket descriptor
// char - address of the input buffer area
// int - buffer area length
// int - flags (not used here)

RspBufAdr = %addr(data);
RspBufLen = %size(data);

RecLen = recv(s: RspBufAdr : RspBufLen : 0);
If (RecLen < 1);
data = 'ERR: No Reply. ';
return -1;
Endif;

// Translate: QDCXLATE API parameters
// Length of data being converted Input Packed(5,0)
// Conversion data I/O Char(*)
// ASCII In, EBCDIC Out
// SBCS conversion table name Input Char(10)

Translate(RecLen : data : 'QTCPEBC' );




message: 1
date: Fri, 11 Feb 2011 16:25:54 -0600
From: Scott Klement <midrange-l@xxxxxxxxxxxxxxxx>
subject: Re: Socket Programming: Stuck on Reply

Hi Charlie,

You pointed out that the application is hanging on GetReply(). Did you troubleshoot the GetReply() routine?

What does GetReply() do? Is that something you wrote?

If the GetReply() is the same one that was in the CLIENT1 sample program (the one from the article you linked to) it was >>
specifically written to retrieve an SMTP response line. Since your application doesn't use SMTP, I don't know why'd leave that >>partof the code unchanged! So, I hope you changed it to suit your app?


On 2/11/2011 3:37 PM, Versfelt, Charles wrote:

I'm trying to do socket programming for the first time, the client has sent a server which has been set up by operations, I need to access via socket program to call their APIs.

I'm trying to follow the instructions from this article
http://systeminetwork.com/article/introduction-tcpip-programming
And also referring to sample programs.

And using the /copy socket_h

My program is hanging up on the Reply. It sits there and hangs.

Ops has set up the new server in WRKSRVTBLE as:
Service Port Protocol
E0007825019-1 1200 tcp

The IP address of the new server is in the Host Table entries as E0007825019-01.

Getting the IP address works.

p_hostent = gethostbyname('E0007825019-01');
if (p_hostent = *NULL);
@preturn = 'CPCON01';
@prtnmsg = 'Host lookup failed. ';
joblog('Host lookup failed.');
return;
else;
addr = h_addr;
endif;


Getting the port works.

p_servent = getservbyname('E0007825019-1': 'tcp');
if (p_servent<> *NULL);
port = s_port;
else;
port = 1200;
endif;

Creating the socket works

s = socket(AF_INET: SOCK_STREAM: IPPROTO_TCP);
If (s = -1);
@preturn = 'CPCON02';
@prtnmsg = 'Socket failed. ';
joblog('Socket failed!');
return;
endif;

I connect to the server

connto = *ALLx'00';
connto.sin_family = AF_INET;
connto.sin_addr = addr;
connto.sin_port = port;


if ( connect(s: %addr(connto): %size(connto)) = -1 );
callp close(s);
@preturn = 'CPCON03';
@prtnmsg = 'Connect failed. ';
joblog('Connect failed!');
return;
endif;

Just to check the value, at one point I put this value into a variable:
connect(s: %addr(connto): %size(connto) The value is 0.
It's certainly not -1, the error.

The program sits and hangs on the if statement:

if ( GetReply(s)<> 220 );
@preturn = 'CPCON04';
@prtnmsg = 'Server Not Ready ';
callp close(s);
joblog('Not ready for SMTP requests.');
return;
endif;

Any help I get will be greatly appriciated... If I need to provide more information please let me know.
I don't see anything in the job log pointing me to what's happening.

ALSO, by the way... Not sure if this has anything to do with my problem...
Is it unusual that, I connect using these commands, Then the first
thing the vendor wants me to do in their specs is to send them a CONNECT command?

Or is what they're requesting somehow supposed to be part of my connect?

They want me to connect by sending them a string like this:
'0000000022CONNECT|CLIENTTYPE|20|CLIENTID|222|'

I took that to mean, that once I'm connected (after my if statement) the next thing I do is this:

SendAscii(s: '0000000022CONNECT|CLIENTTYPE|20|CLIENTID|222|');

Does it make sense that I connect (to the server via socket) and then send them their bar-delimited connect command? It's like I'm connecting to connect...

Charlie





As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

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.