REXX programming hints and tips

This topic contains information that you might find helpful when you use REXX sockets.

Capitalization

Throughout the documentation, REXX socket API commands and constants are capitalized when they are used in descriptive text. For example, the LISTEN command places a socket descriptor in passive mode.

Quotation marks

Throughout the documentation, REXX socket API commands and constants are enclosed in quotation marks (") when they are used in code examples, for example, src = socket("ACCEPT",sockfd);.

Although the use of quotation marks is optional, consider using quotation marks to prevent programming errors. Using quotation marks forces the socket function to use string literals rather than REXX variables. When REXX encounters an uninitialized variable, it initializes that variable with the name of the variable. The command socket(ACCEPT,sockid) is valid because the uninitialized variable ACCEPT is initialized to the character string ACCEPT. However, if the program initializes the ACCEPT variable with a value other than the character string ACCEPT, the socket function fails.

Guideline: Unless otherwise indicated by a specific socket command, all socket commands and constant values must be passed as character strings.

Splitting a function over multiple lines

The socket function, with parameters, might exceed 80 characters. In such cases, you can split the function across multiple lines by using the REXX continuation character, a comma (,). Consider the following examples:
Continuing a string across two lines
l_string1 = "This is a string split between",
            "two lines.";
Continuing a string when the continuation occurs on a parameter boundry
src = socket("GETADDRINFO","CHILE",,
             23,"AI_CANONNAMEOK");

In this example, the first comma after the parameter "CHILE" indicates the end of the parameter. The second comma indicates that the REXX statement continues on the next line.

Return codes

To avoid problems, an application should check the return code of a socket command after each socket call. The examples in this topic do not always follow this recommendation. The examples are intended to show how to issue the socket command.

Guideline: Use either the REXX PARSE feature or the WORD function to access the return code. For example,
parse var l_retcode src remainder;
if src = 0 then do 
   /* DO SOME STUFF */
end;
else do 
   /* Process the error */
end;

Allocating and deallocating socket sets

To use the socket commands provided by the REXX socket function, a socket set must be active. To allocate a socket set, use the INITIALIZE socket command. The INITIALIZE command creates a socket set and can support multiple socket calls. The subtaskid value identifies the socket set and usually corresponds to the application name. The service value indicates the TCP/IP stack name to form an affinity with.

Restriction: When the INITIALIZE command is issued, the REXX socket API forms an affinity with the default TCP/IP stack. In an INET environment, the affinity is created with the active stack. In a CINET environment, the affinity is created with the default stack. The default stack is determined either by the first BPXPRMxx SUBFILESYSTYPE statement or by the SUBFILESYSTYPE statement with the keyword DEFAULT. For additional information, see z/OS® Communication Server: MVS™ Initialization and Tuning Reference.
Guideline: Before you exit the program or when you do not need the socket environment, use the TERMINATE socket command to deallocate the socket set.

Blocking and nonblocking mode

A socket can be in blocking or nonblocking mode. In blocking mode, commands such as SEND and RECV block the caller until either the operation is completed successfully or an error occurs. In nonblocking mode, the caller is not blocked, but the operation ends immediately with either the 35 EWOULDBLOCK or 36 EINPROGRESS return code. Use the FCNTL or IOCTL commands to switch the socket between blocking and nonblocking modes.

When a socket is in nonblocking mode, you can use the SELECT command to monitor the socket for one or more socket events. The socket can be monitored for events that indicate that the socket is ready for writing or reading, or whether an exception has occurred.

Transferring a socket to a subtask

If the application uses the GIVESOCKET and TAKESOCKET commands to transfer a socket from a parent program to a subtask, both the parent and subtask must agree on a mechanism for exchanging the client ID and the socket descriptor. The parent program can use the SELECT command to monitor when the subtask takes the socket. After the subtask takes the socket, the parent then can close the socket that was given.

SO_ASCII and SO_EBCDIC socket options

The socket options SO_ASCII and SO_EBCDIC identify the socket data type for use by the REXX RXSOCKET program. Setting the SO_EBCDIC option to ON has no effect, and setting the SO_ASCII option to ON causes all incoming data on the socket to be translated from ASCII to EBCDIC and all outgoing data on the socket to be translated from EBCDIC to ASCII.