Connecting to a server in a client program

To connect to a server, the client must know the server name. This topic describes how to determine a server name and connect to that server.

Note: Examples are written in C language and REXX.

To connect to the server, the client places the port number and the IP address of the server into a sockaddr_in structure like the bind() call. If the client does not know the server IP address, but it does know the server host name, the gethostbyname() call is called to translate the host name into its IP address. Any trailing blanks will be removed from the specified name before trying to resolve it to an IP address.

The client then calls connect() as shown in the following C language example of the connect() call:
connect(s, name, namelen);
When the connection is established, the client uses its socket to communicate with the server.

If you need to determine a server name while writing in REXX and you know only the host name, you must resolve the host name into one or more IP addresses using the gethostbyname() call as shown in Figure 1:

Figure 1. Finding the IP address of a server host using gethostbyname()
 /*----------------------------------------------------------------*/ 
 /* Find IP addresses of server host                               */  
 /*----------------------------------------------------------------*/ 
 servipaddr = DoSocket('Gethostbyname', tpiserver)
 if sockrc <> 0 then do
    say 'Gethostbyname failed, rc='sockrc 
    say sockval 
    x=Doclean
    exit(sockrc) 
end

The REXX gethostbyname() call returns a list of IP addresses if the host is multiply defined as a home host. You can parse the REXX string and place the IP addresses into a REXX stem variable using the following piece of REXX code:

 /*----------------------------------------------------------------*/
 /* Parse returned IP address list                                 */  
 /*----------------------------------------------------------------*/ 
 numips = words(servipaddr)
 do i = 1 to numips
   sipaddr.i = word(servipaddr, i)
 end
 sipaddr.0 = numips 

If you issue a connect call to an IP address currently not available, your connect call times out with an error number of 60 (ETIMEDOUT). The socket you used on such a failed connect call cannot be reused for another connect() call. You have to close the existing socket and get a new socket before you reissue the connect call using the next IP address in the list of IP addresses returned by the gethostbyname() call.

The connect call can be placed in a loop that terminates when a connect is successful, or the list of IP addresses is exhausted. The following sample illustrates this process.

 /*----------------------------------------------------------------*/  
 /*                                                                */ 
 /* Get a socket and try to connect to the server                  */  
 /*                                                                */ 
 /* If connect fails (ETIMEDOUT), we must close the socket,        */
 /* get a new one and try to connect to the next IP address        */
 /* in the list, we received on the gethostbyname call.            */  
 /*                                                                */
 /*----------------------------------------------------------------*/ 
i=1
connected = 0
do until (i > sipaddr.0 | connected) 
   sockdescr = DoSocket('Socket')
   if sockrc <> 0 then do
      say 'Socket failed, rc='sockrc 
      exit(sockrc) 
   end
   name = 'AF_INET '||tpiport||' '||sipaddr.i 
   sockval = DoSocket('Connect', sockdescr, name)
   if sockrc = 0 then do
      connected = 1 
   end
   else do
      sockval = DoSocket('Close', sockdescr)
      if sockrc <> 0 then do
         say 'Close failed, rc='sockrc 
         exit(sockrc)
      end
   end
   i = i + 1
end
if connected then do  
   say 'Connect failed, rc='sockrc
   exit(sockrc) 
end