REXX Tutorial

A simple mirror server and client

With the above information we can already write the first small socket application in REXX: a mirror server with a matching client program. The mirror server receives a string from the client, reverses the order of the characters in the string and returns it back to the client. After returning the mirrored string the communication will be closed down.

Mirror client

Let's have a look at the client program first:


    /* MCLIENT.CMD - IBM REXX Sample Program                */

    /* Parameters:                                          */

    /*   Server: alias name of mirror server                */

    Parse Arg Server



    /* Load REXX Socket library if not already loaded       */

    If RxFuncQuery("SockLoadFuncs") Then

     Do

       Call RxFuncAdd "SockLoadFuncs","RXSOCK","SockLoadFuncs"
       Call SockLoadFuncs

     End



    /* Ask user for string to send to the mirror server     */

    Say "Please enter a string that should be mirrored"
    Parse Pull InpString



    /* create a TCP socket                                  */

    Socket = SockSocket("AF_INET", "SOCK_STREAM", "0")



    /* resolve server name alias to dotted IP address       */

    Call SockGetHostByName Server, "Host.!"


    /* connect the new socket to the specified server       */

    Host.!family = "AF_INET"
    Host.!port = 1996

    Call SockConnect Socket, "Host.!"


    /* send the input string to the mirror server           */

    Call SockSend Socket, InpString



    /* receive answer from mirror server and close socket   */

    Call SockRecv Socket, "OutString", 256

    Call SockShutDown Socket, 2

    Call SockClose Socket



    Say "The string '" || InpString || "' was mirrored to"
    Say "'" || OutString || "'."
The client program first loads the REXX socket library if it is not already loaded (which is checked with a call to 'RxFuncQuery'). The socket is created after the user has been asked for the string that will be sent to the mirror server. The parameters used on the 'SockSocket' call will create a default 'stream type' socket. Stream type sockets support full duplex communication between two partners. There are other socket types, e.g. 'datagram' or 'raw' sockets which operate connectionless by sending only messages to the recipients. These socket types will not be discussed in this tutorial.

The new socket is not connected initially. To connect it to another workstation we have to call 'SockConnect'. 'SockConnect' expects a stem variable with the following information:

Normally the server alias will be specified at the command line which has to be resolved to its dotted IP address with a call to 'SockGetHostByName'. The resolved address can then be used to connect the socket to the server with a call to 'SockConnect'. After the connection has been established the input string is sent to the server and the program waits for the response from the server which is then stored in the variable 'OutString'. The call to 'SockRecv' is a blocking call, i.e. it will not return before the server has sent an answer or an error occurred. The socket is finally cleaned up, closed, and then the result from the mirror server is shown on the screen.

Mirror server

The server program needs only a few more lines to setup the server connection queue:


    /* MSERVER.CMD - IBM REXX Sample Program                */



    /* Load REXX Socket library if not already loaded       */

    If RxFuncQuery("SockLoadFuncs") Then

     Do

       Call RxFuncAdd "SockLoadFuncs","RXSOCK","SockLoadFuncs"
       Call SockLoadFuncs

     End



    /* create a TCP socket for client connection requests   */

    Socket = SockSocket("AF_INET", "SOCK_STREAM", "0")



    /* find out local IP address                            */

    Host.!addr = SockGetHostId()



    /* Bind socket to well known port 1996                  */

    Host.!family = "AF_INET"
    Host.!port = 1996

    Call SockBind Socket, "Host.!"


    /* create a connection queue for 1 client               */

    Call SockListen Socket, 1



    /* wait for a client to connect                         */

    Say "Waiting for a client to connect..."
    ClientSocket = SockAccept(Socket)

    Say "Client has established connection."


    /* we don't want any more clients, close request socket */

    Call SockShutDown Socket, 2

    Call SockClose Socket



    /* read string from client, reverse it and send it back */

    Call SockRecv ClientSocket, "InpString", 256

    Say "String read from client: '" || InpString || "'"
    OutString = Reverse(InpString)

    Call SockSend ClientSocket, OutString



    /* close client socket                                  */

    Call SockShutDown ClientSocket, 2

    Call SockClose ClientSocket

Initialization of the server program is done in exactly the same way as for the client. The REXX socket library is loaded and then a stream type socket is created. The new socket will then be registered with the well known port number 1996 on the server by calling 'SockBind'. The dotted IP address of the server needed by this call is retrieved with 'SockGetHostId'. The IP address of the server and the well known port number will be the only information needed by a client to connect to the mirror server. Port numbers below 1024 should not be used for private applications because they are reserved for TCP/IP specific applications, such as FTP, TELNET, etc..

Before a client can connect to the server a client connection request queue has to be created using the 'SockListen' function. This queue, whose size can be specified on the 'SockListen' call, is used to serialize multiple connection requests on the server. Every client that wants to connect to the server will open a connection to the well known port on the server and will get added to the connection request queue automatically. The server has to call 'SockAccept' to accept such a connection request from the client. 'SockAccept' will return a new socket id that can be used to communicate with the client. The original socket still exists and can be used to allow more clients to connect to the server by issuing another 'SockAccept' call.

In our example we won't accept any more clients so we can simply close the original socket, read the input string from the client socket, reverse the string, send it back to the client, and close the socket. It's not important that the server keeps its end of the socket open until the client has read all the data. Data still in the socket will only be destroyed if both ends of the socket are closed.

These two programs do not check any error conditions since they are only for demonstration purposes. Of course all calls to the REXX socket library report error conditions if they occur. For a complete reference of these error conditions have a look at the documentation of the REXX socket library and also at the TCP/IP programming reference.


[ IBM REXX homepage | Previos page | Next page | Tutorial Index | Object REXX homepage ]
[ IBM homepage | Order | Search | Contact IBM | Help | (C) | (TM) ]
This page is at http://www2.hursley.ibm.com/rexxtut/socktut4.htm