/* 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:
/* 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 ClientSocketInitialization 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.