This section documents the easiest, by far, socket API to call. The close() API. This API is used to disconnect a connected socket, and destroy the socket descriptor. (In other words, to use the socket again after calling close() you have to call socket() again).
Here's the IBM manual page that describes the close() API:< http://publib.boulder.ibm.com/pubs/html/as400/v4r5/ic2924/info/apis/close.htm
The manual tells us that the prototype for close() looks like this:
int close(int fildes)
So, the procedure's name is 'close' and it accepts one parameter, an integer. It also returns an integer. The RPG prototype looks like this:
D close PR 10I 0 ExtProc('close') D sock_desc 10I 0 value
To call it, we can simply to:
C eval rc = close(s) C if rc < 0 C*** Socket didn't close. Now what? c endif
Or, more commonly (because there isn't much we can do if close() fails) we do something like this:
C callp close(s)
Too easy to be a UNIX-Type API, right? Well, never fear, there's one complication. The system uses the same close() API for closing sockets that it uses for closing files in the integrated file system.
This means that if you use both sockets and IFS reads/writes in your program, that you only need to define one prototype for close(). Handy, right? Unfortunately, most people put all of the definitions needed for socket APIs into one source member that they can /COPY into all of the programs that need it. Likewise, the IFS prototypes and other definitions are put into their own /COPY member.
When you try to use both /COPY members in the same program, you end up with a duplicate definition of the close() API, causing the compiler to become unhappy.
The solution is relatively simple... When we make a header file for either sockets or IFS, we use the RPG /define and /if defined directives to force it to only include the close() prototype once. So, our prototype will usually look like this:
D/if not defined(CLOSE_PROTOTYPE) D close PR 10I 0 ExtProc('close') D sock_desc 10I 0 value D/define CLOSE_PROTOTYPE D/endif