REXX Tutorial

REXX/Sockets on VM

The last topic of this tutorial will show you the differences of the REXX/SOCKET implementation on VM. The main difference of this implementation is in the used syntax. Nearly all functions have equivalents on both platforms. Only the handling of multiple clients on the server side is done differently on VM since you cannot start a new session to communicate with each new client.

Function equivalents

Initialize the socket interface at program startup:
OS/2
If RxFuncQuery("SockLoadFuncs") Then Do

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

End
VM
/* initialize socket interface for MYPROG EXEC */

Call Socket "Initialize", "MYPROG"

Deregister socket interface:

OS/2
Call SockDropFuncs
VM
/* deregister socket interface for MYPROG EXEC */

Call Socket "Terminate"

Create an unconnected socket:

OS/2
Socket = SockSocket("AF_INET", "SOCK_STREAM", "0")
VM
/* create a new socket and activate ASCII translation */

Parse Value Socket("Socket") With SockRc Sock

Call Socket "SetSockOpt", Sock, "SOL_SOCKET", "SO_ASCII", "On"

Connect a socket to a host/port address:

OS/2
Host.!family = "AF_INET"

Host.!address = "9.164.0.197"  /* set remote host address */

Host.!port = 1996

Call SockConnect Socket, "Host.!"
VM
Call Socket "Connect", Sock, "AF_INET 1996 9.164.0.197"

Send a string over a socket:

OS/2
Call SockSend Socket, "This is my test string"
VM
Call Socket "Send", Sock, "This is my test string"

Receive a string from a socket:

OS/2
/* receive max. 1024 characters */

BytesRcvd = SockRecv(Socket, "InBuffer", 1024)

Say InBuffer
VM
Parse Value Socket("Recv", Sock) With SockRc BytesRcvd InBuffer

Say InBuffer

Shutdown a socket:

OS/2
Call SockShutDown Socket, 2
VM
Call Socket "ShutDown", Sock

Close a socket:

OS/2
Call SockClose Socket
VM
Call Socket "Close", Sock

Bind a socket to a well known port on the server:

OS/2
Host.!family = "AF_INET"

Host.!port = 1996

Host.!address = "9.164.0.197"  /* set local host address */

Call SockBind Socket, "Host.!"
VM
LocalAddr = "9.164.0.197"

Call Socket "Bind", Sock, "AF_INET 1996" LocalAddr

Listen on a socket for a client connection request:

OS/2
/* accept max. 5 clients simultaneously */

Call SockListen Socket, 5
VM
/* accept max. 5 clients simultaneously */

Call Socket "Listen", Sock, 5

Accept a connecting client:

OS/2
ClientSock = SockAccept(Socket)
VM
/* socket handling on VM is done via REXX/WAIT package! */

Parse Value Socket("Accept", Sock) With SockRc ClientSock ClientInfo

Find out local IP address:

OS/2
LocalAddr = SockGetHostId()
VM
LocalAddr = Socket("GetHostId")

Resolve a host name alias to an IP address:

OS/2
Call SockGetHostByName "www2.hursley.ibm.com", "Host.!"

Say Host.!addr
VM
Parse Value Socket("GetHostByName", "www2.hursley.ibm.com") With SockRc HostAddr

Say HostAddr

VM implementation of mirror sample

The following two listings show the mirror client and server sample in the VM implementation. Besides the different function call syntax the main difference can be found in the server program. To be able to process requests from multiple sockets the REXX/WAIT package is used. The 'Wait' function of the package receives a condition string on which events the program wants to react. The mirror server wants to react on every read required for any socket. The matching condition string for this would be "Socket Read *". Instead of the asterisk you can also specify one or more socket handles on which a program wants to react. This would be useful if more than one server programs is running on the system.

This is the client program:



    /* MCLIENT EXEC - IBM REXX Sample Program               */

    /* Parameters:                                          */

    /*   Server: alias name of mirror server                */

    Parse Arg Server



    /* Initialize REXX Socket function package              */

    Call Socket "Initialize", "MCLIENT"


    /* 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 and activate ASCII translation   */

    Sock = Socket("Socket")

    Call Socket "SetSockOpt",Sock,"SOL_SOCKET","SO_ASCII","On"


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

    Call Socket "Connect", Sock, "AF_INET 1996" Server



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

    Call Socket "Send", Sock, InpString



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

    Parse Value Socket("Recv", Sock) With BytesRcvd OutString

    Call Socket "ShutDown", Sock

    Call Socket "Close", Sock



    Say "The string '" || InpString || "' was mirrored to"
    Say "'" || OutString || "'."


    /* deregister socket function package for this process  */

    Call Socket "Terminate"
    Exit



    /********************************************************/

    /*                                                      */

    /* Procedure: Socket                                    */

    /* Purpose:   Forward the socket call and return the    */

    /*            return string only, not the return code.  */

    /* Arguments: arguments to 'SOCKET' function            */

    /* Returns:   return string of 'SOCKET' function        */

    /*            without return code                       */

    /*                                                      */

    /********************************************************/

    Socket: Procedure Expose SockRc

      a0 = Arg(1)

      a1 = Arg(2)

      a2 = Arg(3)

      a3 = Arg(4)

      a4 = Arg(5)

      a5 = Arg(6)

      a6 = Arg(7)

      a7 = Arg(8)

      a8 = Arg(9)

      a9 = Arg(10)

      Parse Value 'SOCKET'(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9) With SockRc Res

      Return Res

And finally the server program:


    /* MSERVER EXEC - IBM REXX Sample Program               */

    /* Initialize REXX Socket function package              */

    Call Socket "Initialize", "MSERVER"
    /* create a TCP socket for client connection requests   */

    Sock = Socket("Socket")

    Call Socket "SetSockOpt",Sock,"SOL_SOCKET","SO_ASCII","On"


    /* find out local IP address                            */

    HostAddr = Socket("GetHostId")



    /* Bind socket to well known port 1996                  */

    Call Socket "Bind", Sock, "AF_INET 1996" HostAddr



    /* create a connection queue for 1 client               */

    Call Socket "Listen", Sock, 1



    /* set mode of socket to non blocking                   */

    Call SetValue "Socket" Sock "Non-Blocking"
    Say "Waiting for a client to connect..."


    /* now wait for a client to connect                     */

    Do Forever

      /* wait for a socket read event or console input      */

      Event = Wait("Socket Read *", "Cons")

      Parse Upper Var Event WRc Event Rest

      Select

        When Event = "CONS" Then Do

          If Rest = "EXIT" Then

            Leave

          Else

            Say "Enter 'Exit' to leave program"
        End



        When Event = "SOCKET" Then Do

          Parse Var Rest KeyWord EvtSock



          If KeyWord = "READ" & EvtSock = Sock Then Do

            /* a client has connected to the request socket */

            /* show info available on the client            */

            Parse Value Socket("Accept", Sock) with CltSock CltInfo

            Say "Client has established connection:" CltInfo



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

            Call Socket "ShutDown", Sock

            Call Socket "Close", Sock

          End



          If KeyWord = "READ" & EvtSock \= Sock Then Do

            /* a client has sent a string to mirror         */

            Parse Value Socket("Recv", EvtSock) with Bytes InpString

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

            Call Socket "Send", EvtSock, OutString



            /* close the client socket                      */

            Call Socket "ShutDown", EvtSocket

            Call Socket "Close", EvtSocket



            /* we have answered the request, quit program   */

            Leave

          End

        End



        Otherwise Nop

      End

    End



    /* deregister socket function package for this process  */

    Call Socket "Terminate"
    Exit



    /********************************************************/

    /*                                                      */

    /* Procedure: Socket                                    */

    /* Purpose:   Forward the socket call and return the    */

    /*            return string only, not the return code.  */

    /* Arguments: arguments to 'SOCKET' function            */

    /* Returns:   return string of 'SOCKET' function        */

    /*            without return code                       */

    /*                                                      */

    /********************************************************/

    Socket: Procedure Expose SockRc

      a0 = Arg(1)

      a1 = Arg(2)

      a2 = Arg(3)

      a3 = Arg(4)

      a4 = Arg(5)

      a5 = Arg(6)

      a6 = Arg(7)

      a7 = Arg(8)

      a8 = Arg(9)

      a9 = Arg(10)

      Parse Value 'SOCKET'(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9) With SockRc Res

      Return Res


[ 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/socktut8.htm