3.5. The close() API call

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