| Previous | Contents | Index | 
To bind a socket, specify a local interface address and local port number for the device socket.
If the application needs to receive incoming multicast or broadcast 
datagrams destined for a specific UDP port, see Section 2.10 for 
information about specifying the SO_REUSEPORT option when you bind the 
socket.
2.4.1 Binding Sockets with OpenVMS System Services 
Use the IO$_SETMODE or IO$_SETCHAR function of the $QIO system service to bind a socket.
| The process must have a system user identification code (UIC), SYSPRV, BYPASS, or OPER privileges to bind port numbers 1 to 1023. | 
Example 2-5 shows a TCP/IP server using the IO$_SETMODE function to bind sockets.
| Example 2-5 Binding Socket Using OpenVMS System Services | 
|---|
| 
 
/* 
** 
** Bind the socket to a local address. 
** 
*/ 
    addrLength = sizeof( localAddr ); 
    memset( &localAddr, 0, sizeof( localAddr )); 
    localAddr.sin_family = AF_INET; 
    localAddr.sin_addr.s_addr = INADDR_ANY; 
    localAddr.sin_port = htons( SERVER_PORT ); 
 
/* 
** 
** Declare and populate a string descriptor, (struct dsc$descriptor_s), 
** as defined in <descrip.h>. 
** 
*/ 
    localAddrDSC.dsc$a_pointer = (char*)&localAddr; 
    localAddrDSC.dsc$w_length  = (long)addrLength; 
 
/* 
** 
**  Attempt to Bind the device socket to the local host address. 
**  Use the function code of IO$_SETMODE, passing the local 
**  address information as a descriptor to P3. 
** 
**  NOTE: The functionality of this call, to bind the socket, and the 
**  functionality of the sys$qiow call, to create the socket, could be 
**  combined into one call. 
** 
*/ 
    sysSrvSts = sys$qiow( 0,             /* efn.v | 0 */ 
                          IOChannel,     /* chan.v */ 
                          IO$_SETMODE,   /* func.v */ 
                          &iosb,         /* iosb.r | 0 */ 
                          0, 0,          /* astadr, astprm: UNUSED */ 
                          0, 0,          /* p1, p2  UNUSED */ 
                          &localAddrDSC, /* p3.d Socket bind parameter */ 
                          0, 0, 0        /* p4, p5, p6 UNUSED */ ); 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        { 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
 
 | 
Example 2-6 shows an example of a TCP/IP server using the bind() routine to bind a socket name.
| Example 2-6 Binding a Socket Using C Socket Programming | 
|---|
| 
#include <types.h> 
#include <in.h> 
#include <socket.h> 
#include <unixio.h> 
#include <string.h> 
 
#define PORTNUM 1234 
   .
   .
   .
 
main() { 
 int r, s, i; 
 struct sockaddr_in lcladdr; 
 char *message = "Hello, world!\r\n"; 
 
 lcladdr.sin_family = AF_INET; 
 lcladdr.sin_addr.s_addr = INADDR_ANY; 
 lcladdr.sin_port = htons(PORTNUM); 
   .
   .
   .
 i = bind( s, 
  (struct sockaddr *)&lcladdr,(1)
          sizeof(lcladdr));(2)
   .
   .
   .
 | 
In this example, the bind() routine specifies the socket descriptor previously created with a call to the socket() routine, as follows:
Only server programs that use TCP need to set a socket to be a 
listener. This allows the program to receive incoming connection 
requests. (TCP, as a stream protocol, requires a connection. UDP, a 
datagram protocl, does not.) To set a socket to listen for connection 
requests, specify the number of incoming requests that can wait to be 
queued for processing.
2.5.1 Listening to a Socket with OpenVMS System Services
Example 2-7 shows how to use the IO$_SETMODE function to set the socket to listen for requests.
| Example 2-7 Setting the Socket to Listen Using OpenVMS System Services | 
|---|
| 
 
#define SERVER_QLENGTH 3 
 
/* 
** 
**  Attempt to inform the network driver that it should enqueue multiple 
**  simultaneous incoming connection requests. 
**  Use the function code IO$_SETMODE, passing the desired queue 
**  length by value to P4.  Should the queue of connection requests waiting to 
**  be accepted be at the specified limit, new connection requests are 
**  automatically rejected by the network driver. 
** 
*/ 
    sysSrvSts = sys$qiow( 0,              /* efn.v | 0 */ 
                          IOChannel,      /* chan.v */ 
                          IO$_SETMODE,    /* func.v */ 
                          &iosb,          /* iosb.r | 0 */ 
                          0, 0,           /* astadr, astprm: UNUSED */ 
                          0, 0, 0,        /* p1, p2, p3 UNUSED */ 
                          SERVER_QLENGTH, /* p4.v Queue length */ 
                          0, 0            /* p5, p6 UNUSED */   ); 
 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        { 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
 | 
| Although you can issue separate $QIO calls for socket create, bind, and listen operations, you can also perform these operations with one $QIO call. Note that socket name means the same as socket address, and it represents the association of host address and port information. | 
Example 2-8 shows a TCP/IP server using the bind() routine to set the socket to listen for requests.
| Example 2-8 Setting the Socket to Listen Using C Socket Programming | 
|---|
| 
#include <types.h> 
#include <in.h> 
#include <socket.h> 
#include <unixio.h> 
#include <string.h> 
 
#define PORTNUM 1234 
 
main() { 
 int r, s, i; 
 struct sockaddr_in lcladdr; 
 char *message = "Hello, world!\r\n"; 
        memset( &lcladdr, 0, sizeof(lcladdr)); 
 lcladdr.sin_family = AF_INET; 
 lcladdr.sin_addr.s_addr = INADDR_ANY; 
 lcladdr.sin_port = htons(PORTNUM); 
   .
   .
   .
 i = listen(s,(1) 1);(2)
 | 
In this example of a listen() routine:
You can initiate a connection through a TCP client using either a stream socket or datagram. However, you must follow the guidelines listed below:
To initiate a connection to a remote host, issue the $QIO system service with the IO$_ACCESS function and the p3 argument. The p3 argument of the IO$_ACCESS function is the address of an item_list_2 descriptor that contains the remote socket name.
Example 2-9 shows an example of a TCP/IP client using the IO_$ACCESS function to initiate a connection.
The internet address received by the program identifies the remote host. To map the internet address to the host name, use a $QIO system service with the IO$_ACPCONTROL function (see Chapter 4).
| Example 2-9 Initiating a Connection Using OpenVMS System Services | 
|---|
| 
 
 
/* 
** 
**  Get the remote server host name from the user and set up the remote 
**  address structure. 
** 
*/ 
    memset( &remoteAddr, 0, sizeof( remoteAddr )); 
    remoteAddr.sin_family = AF_INET; 
    remoteAddr.sin_port = htons( SERVER_PORT_NUMBER ); 
 
    /* Continue to prompt the user for a valid server host name. */ 
    memset( IOBuff, 0, MaxBuff ); 
    printf( "\n    Enter the host name where the server is running : " ); 
    scanf( "%s", IOBuff ); 
    while( (hostentptr = gethostbyname( IOBuff )) == (struct hostent*)NULL ) 
        { 
        printf( "    Host %s could not be found.\n", IOBuff ); 
        memset( IOBuff, 0, MaxBuff ); 
        printf( "\n    Enter the host name where the server is running : " ); 
        scanf( "%s", IOBuff ); 
        } 
 
    remoteInAddr.s_addr = *(int*)(hostentptr->h_addr); 
    addrStr = (char*)inet_ntoa( remoteInAddr ); 
    printf( "\n    connecting to: %s   %s\n", hostentptr->h_name, 
            addrStr )); 
 
    remoteAddr.sin_addr = *((struct in_addr*)hostentptr->h_addr ); 
    remoteAddrDSC.dsc$a_pointer = (char*)&remoteAddr; 
    remoteAddrDSC.dsc$w_length  = sizeof( remoteAddr ); 
 
/* 
** 
**  Attempt to connect the device socket to the local host address. 
**  Use the function code IO$_ACCESS, passing the remote 
**  address information as a descriptor to P3. 
** 
**  NOTE: The functionality of this calln to connect the socket, and 
**  the functionality of the sys$qiow call, to create the socket, 
**  could be combined into one call. 
** 
*/ 
    sysSrvSts = sys$qiow( 0,              /* efn.v | 0 */ 
                          IOChannel,      /* chan.v */ 
                          IO$_ACCESS,     /* func.v */ 
                          &iosb,          /* iosb.r | 0 */ 
                          0, 0,           /* astadr, astprm: UNUSED */ 
                          0, 0,           /* p1, p2 UNUSED */ 
                          &remoteAddrDSC, /* p3.d Socket connect parameter */ 
                          0, 0, 0         /* p4, p5, p6 UNUSED */ ); 
 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        { 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
 
 | 
To initiate a connection to a remote host, issue the connect() routine. Example 2-10 shows an example of a TCP/IP client using the connect() routine to initiate a connection to a remote server.
| Example 2-10 Initiating a Connection Using C Socket Programming | 
|---|
| 
   .
   .
   .
        int     sock_1;                         /* socket */ 
static  char    message[] = "Hi there."; 
static  struct  sockaddr_in sock2_name;         /* Address struct for socket2.*/ 
        struct  hostent         hostentstruct;  /* Storage for hostent data.  */ 
        struct  hostent         *hostentptr;    /* Pointer to hostent data.   */ 
        static  char            hostname[256];  /* Name of local host.        */ 
        int     flag; 
        int     retval;                          /* helpful for debugging */ 
        int     shut = FALSE;                 /* flag to cleanup */ 
   .
   .
   .
        /* 
         * Fill in the name & address structure for socket 2. 
         */ 
        sock2_name.sin_family = hostentstruct.h_addrtype; 
        sock2_name.sin_port = htons(atoi(argv[2])); 
        sock2_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr); 
 
 
 
 
        /* 
         * Connect socket 1 to sock2_name. 
         */ 
        retval = connect(sock_1, &sock2_name, sizeof (sock2_name)); 
        if (retval) 
                { 
                perror("connect"); 
                cleanup(shut, sock_1); 
                } 
 
 
 | 
Your server program must be able to accept incoming connection requests 
from client programs to successfully use TCP.
2.7.1 Accepting a Connection Using OpenVMS System Services
To accept a connection request, use the following procedure:
| Specifying the IO$_ACCESS function is mandatory for TCP/IP. The IO$_ACCESS function uses the p4 argument only with the IO$M_ACCEPT modifier. | 
Example 2-11 shows a TCP server using the IO$_ACCESS function with the IO$M_ACCEPT modifier to accept incoming connection requests.
| Example 2-11 Accepting an Incoming Connection Request Using OpenVMS System Services | 
|---|
| 
/* 
** 
** Assign a new channel, for the new connection, to the network device, 
** "TCPIP$DEVICE:". 
** 
*/ 
        sysSrvSts = sys$assign( &devDSC,         /* devnam.d */ 
                                &IOChanClient,   /* chan.r */ 
                                0,               /* acmode.v | 0 */ 
                                0,               /* mbxnam.d | 0 */ 
                                0                /* flags.v | 0 */  ); 
        if(( sysSrvSts & 1  ) != 1 ) /* Validate the system service status. */ 
            { 
            cleanup( IOChanClient ); 
            cleanup( IOChannel ); 
            errorExit( sysSrvSts, iosb.cond_value ); 
            } 
        remoteAddrInfo.length    = (unsigned int)addrLength; 
        remoteAddrInfo.address   = (char*)&remoteAddr; 
        remoteAddrInfo.retLenPtr = (unsigned int*)&addrLength; 
/* 
** 
**  Attempt to complete the first connections on a queue of pending 
**  connections. 
**  Use the function codes of IO$_ACCESS ORed with IO$M_ACCEPT, passing the 
**  address of the remote address information to P3, and the address 
**  of the new channel to the client to P4. 
** 
**  This queue must have previously been established with a QIO using 
**  function IO$_SETMODE and a queue length passed to P4. 
** 
*/ 
        sysSrvSts = sys$qiow( 0,                /* efn.v | 0 */ 
                              IOChannel,        /* chan.v */ 
                              IO$_ACCESS | 
                                  IO$M_ACCEPT,  /* func.v */ 
                              &iosb,            /* iosb.r | 0 */ 
                              0, 0,             /* astadr, astprm: UNUSED */ 
                              0, 0,             /* p1, P2: UNUSED */ 
                              &remoteAddrInfo,  /* p3.r Remote IP address */ 
                              &IOChanClient,    /* p4.r connection Chan */ 
                              0, 0              /* p5, p6 UNUSED */   ); 
 
        if((( sysSrvSts & 1  ) != 1 ) || /* Validate system service status. */ 
           ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
            { 
            cleanup( IOChanClient ); 
            cleanup( IOChannel ); 
            errorExit( sysSrvSts, iosb.cond_value ); 
            } 
        printf( "    SUCCEEDED in accepting a connections.\n" ); 
        printf( "    The client connection port number is %d\n", 
            htons( remoteAddr.sin_port )); 
        
 | 
2.7.2 Accepting a Connection Using a C Socket Interface 
Example 2-12 shows how to use the accept() routine.
| Example 2-12 Accepting a Connection Request Using C Socket Programming | 
|---|
| 
        /* 
         * Accept connection from socket 2:             
         * accepted connection will be on socket 3 
         */ 
        namelength = sizeof (sock2_name); 
        sock_3 = accept (sock_2,(1)
                         & sock2_name,(2)
                         & namelength);(3)
        if (sock_3 == -1) 
                { 
                perror ("accept"); 
                cleanup( 2, sock_2, sock_3); 
                } 
 | 
In this example of an accept() routine:
Obtaining device socket information is useful if your program has 
management functions or if you have a complex program that uses 
multiple connections you need to track.
2.8.1 Getting Device Socket Information with OpenVMS System Services
To obtain information about the parts of a device socket, use the following OpenVMS system services:
When using the $GETDVI system service, use the channel number (not TCPIP$DEVICE:) as an input parameter to $GETDVIW to obtain the correct unit number and characteristics of an internet pseudodevice. For information on $GETDVI and its parameters, refer to the OpenVMS Programming Concepts Manual and the OpenVMS System Services Reference Manual.
Example 2-13 shows an example of a TCP/IP client using the IO$_SENSEMODE function to get a local socket name.
| Example 2-13 Obtaining Device Socket Information by Using OpenVMS System Services | 
|---|
| 
/* 
** 
** This is a table listing some of the valid combinations of level to optname 
** 
** level: 
**    +-----------------------+---------------------------+----------------+ 
**    | SOL_SOCKET            | TCPIP$C_TCP               | TCPIP$C_RAW_IP | 
**    +-----------------------+---------------------------+----------------+ 
** optname: 
**    +.......................+...........................+................+ 
**    | TCPIP$C_RCVBUF        | TCPIP$C_USELOOPBACK       | TCPIP$C_IP_TTL | 
**    | TCPIP$C_SNDBUF        | TCPIP$C_TCP_NODELAY       | TCPIP$C_IP_TOS | 
**    | TCPIP$C_KEEPALIVE     | TCPIP$C_TCP_PROBE_IDLE    |                | 
**    | TCPIP$C_REUSEADDR     | TCPIP$C_TCP_DROP_IDLE     |                | 
**    |                       | TCPIP$C_FULL_DUPLEX_CLOSE |                | 
**    +-----------------------+---------------------------+----------------+ 
** 
*/ 
 
    setSockOptType  setSockOpt;        /* Struct used to set socket options */ 
    iLSockOptType   setSockOptItemList;/* Item List of setSockOpt(s) */ 
    int             setSockOneOption = 1; 
 
/* 
** 
** Set and validate option name and level. 
** 
*/ 
    setSockOpt.length                 = sizeof( setSockOneOption ); 
    setSockOpt.code                   = TCPIP$M_REUSEADDR; 
    setSockOpt.optBuffAddr            = (char*)&setSockOneOption; 
    setSockOptItemList.length         =  sizeof(  setSockOptType  ); 
    setSockOptItemList.optStructAddr  = (char*) &setSockOpt; 
 
    setSockOptItemList.code = TCPIP$C_SOCKOPT; 
 
/* 
** 
** Attempt to set options on the socket. 
** 
*/ 
    sysSrvSts = sys$qiow( 0,                   /* efn.v | 0 */ 
                          IOChannel,           /* chan.v */ 
                          IO$_SETMODE,         /* func.v */ 
                          &iosb,               /* iosb.r | 0 */ 
                          0, 0,                /* astadr, astprm: UNUSED */ 
                          0, 0, 0, 0,          /* p1, p2, p3, p4 UNUSED */ 
                          &setSockOptItemList, /* p5.r options item list */ 
                          0                    /* p6 UNUSED */   ); 
 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        { 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
 
 | 
| Previous | Next | Contents | Index |