Compaq TCP/IP Services for OpenVMS
Sockets API and System Services Programming


Previous Contents Index

  1. Define a sockchar structure to contain the characteristics of the type of socket.
  2. Initialize the sockchar structure with the address family, protocol family and type of socket.
  3. Assign a channel to a network device using a string descriptor with the logical name of the network pseudodevice and a structure to receive the I/O channel.
  4. Create the socket with a call to SYS$QIOW supplying the channel, the socket characteristics and specifying an IO$_SETMODE function code.

2.3 Binding a Socket (Optional for Clients)

Binding a socket associates a local protocol address (that is, a 32-bit IPv4 address and a 16-bit TCP or UDP port number) with a socket. To bind a socket, specify a local interface address and local port number for the socket.

With the TCP protocol, you can specify an IP address, a port number, both an IP address and port number or neither.

If the application is using the UDP protocol and 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 binding the socket.

2.3.1 Binding a Socket (Sockets API)

Example 2-3 shows an example of a TCP application using the bind() function to bind a socket name.

Note

The process must have a system user identification code (UIC) and the SYSPRV, BYPASS, or OPER privilege to bind port numbers 1 to 1023.

Example 2-3 Binding a Socket (Sockets API)

 
#include <in.h>                     /* define internet related constants,   */ 
                                    /* functions, and structures            */ 
#include <socket.h>                 /* define BSD socket api                */ 
#include <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
#include <string.h>                 /* define string handling functions     */ 
 
 
#define PORTNUM     12345               /* server port number               */ 
 
 
int main( void ) 
{ 
    int sockfd; 
    struct sockaddr_in addr; 
 
    /* 
     * initialize socket address structure 
     */ 
 
    memset( &addr, 0, sizeof(addr) ); 
    addr.sin_family      = AF_INET; 
    addr.sin_port        = htons( PORTNUM ); 
    addr.sin_addr.s_addr = INADDR_ANY; 
 
    /* 
     * create a socket 
     */ 
 
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 
        { 
        perror( "Failed to create socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * bind ip address and port number to socket 
     */ 
 
    if ( bind(sockfd,(1)
 (struct sockaddr *) &addr,(2)
 sizeof(addr)(3)
) < 0 ) 
        { 
        perror( "Failed to bind socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 

In this example, the bind() function:

  1. sockfd specifies the socket descriptor previously created with a call to the socket() function.
  2. addr specifies the address of the sockaddr_in structure that assigns a name to the socket.
  3. sizeof(addr) specifies the size of the sockaddr_in structure.

2.3.2 Binding a Socket (System Services)

Use the IO$_SETMODE or IO$_SETCHAR function of the $QIO system service to bind a socket.

Note

The process must have a system user identification code (UIC), SYSPRV, BYPASS, or OPER privileges to bind port numbers 1 to 1023.

Example 2-4 shows a TCP server using the IO$_SETMODE function to bind sockets.

Example 2-4 Binding a Socket (System Services)

 
#include <descrip.h>                /* define OpenVMS descriptors           */ 
#include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */ 
#include <in.h>                     /* define internet related constants,   */ 
                                    /* functions, and structures            */ 
#include <iodef.h>                  /* define i/o function codes            */ 
#include <ssdef.h>                  /* define system service status codes   */ 
#include <starlet.h>                /* define system service calls          */ 
#include <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
#include <string.h>                 /* define string handling functions     */ 
#include <stsdef.h>                 /* define condition value fields        */ 
#include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */ 
                                    /* structures, and functions            */ 
 
 
#define PORTNUM     12345               /* server port number               */ 
 
struct iosb 
    {                                   /* i/o status block                 */ 
    unsigned short status;              /* i/o completion status            */ 
    unsigned short bytcnt;              /* bytes transferred if read/write  */ 
    void *details;                      /* address of buffer or parameter   */ 
    }; 
 
struct itemlst_2 
    {                                   /* item-list 2 descriptor/element   */ 
    unsigned short length;              /* length                           */ 
    unsigned short type;                /* parameter type                   */ 
    void *address;                      /* address of item list             */ 
    }; 
 
struct sockchar 
    {                                   /* socket characteristics           */ 
    unsigned short prot;                /* protocol                         */ 
    unsigned char type;                 /* type                             */ 
    unsigned char af;                   /* address format                   */ 
    }; 
 
 
int main( void ) 
{ 
    struct iosb iosb;                   /* i/o status block                 */ 
    unsigned int status;                /* system service return status     */ 
    unsigned short channel;             /* network device i/o channel       */ 
    struct sockchar sockchar;           /* socket characteristics buffer    */ 
    struct sockaddr_in addr;            /* socket address structure         */ 
    struct itemlst_2 addr_itemlst;      /* socket address item-list         */ 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */ 
 
    /* 
     * initialize socket characteristics 
     */ 
 
    sockchar.prot = TCPIP$C_TCP; 
    sockchar.type = TCPIP$C_STREAM; 
    sockchar.af   = TCPIP$C_AF_INET; 
 
    /* 
     * initialize socket address item-list descriptor 
     */ 
 
    addr_itemlst.length  = sizeof( addr ); 
    addr_itemlst.type    = TCPIP$C_SOCK_NAME; 
    addr_itemlst.address = &addr; 
 
    /* 
     * initialize socket address structure 
     */ 
 
    memset( &addr, 0, sizeof(addr) ); 
    addr.sin_family      = TCPIP$C_AF_INET; 
    addr.sin_port        = htons( PORTNUM ); 
    addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; 
 
    /* 
     * assign i/o channel to network device 
     */ 
 
    status = sys$assign( &inet_device,      /* device name                  */ 
                         &channel,          /* i/o channel                  */ 
                         0,                 /* access mode                  */ 
                         0                  /* not used                     */ 
                       ); 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to assign i/o channel\n" ); 
        exit( status ); 
        } 
 
    /* 
     * create a socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &sockchar,           /* p1 - socket characteristics  */ 
                       0,                   /* p2                           */ 
                       0,                   /* p3                           */ 
                       0,                   /* p4                           */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to create socket\n" ); 
        exit( status ); 
        } 
 
    /* 
     * bind ip address and port number to socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       &addr_itemlst,       /* p3 - local socket name       */ 
                       0,                   /* p4                           */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to bind socket\n" ); 
        exit( status ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 

2.4 Making a Socket a Listener (TCP Protocol)

Only server programs that use the TCP protocol need to set a socket to be a listener. This allows the program to receive incoming connection requests. As a connection-oriented protocol, TCP requires a connection; UDP, a connectionless protocol, does not.

The listen() function:

2.4.1 Setting a Socket to Listen (Sockets API)

Example 2-5 shows how a TCP server uses the listen() function to set a socket to listen for connection requests and to specify the number of incoming requests that can wait to be queued for processing.

Example 2-5 Setting a Socket to Listen (Sockets API)

 
#include <in.h>                     /* define internet related constants,   */ 
                                    /* functions, and structures            */ 
#include <socket.h>                 /* define BSD socket api                */ 
#include <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
#include <string.h>                 /* define string handling functions     */ 
 
 
#define BACKLOG     1                   /* server backlog                   */ 
#define PORTNUM     12345               /* server port number               */ 
 
 
int main( void ) 
{ 
    int sockfd; 
    struct sockaddr_in addr; 
 
    /* 
     * initialize socket address structure 
     */ 
 
    memset( &addr, 0, sizeof(addr) ); 
    addr.sin_family      = AF_INET; 
    addr.sin_port        = htons( PORTNUM ); 
    addr.sin_addr.s_addr = INADDR_ANY; 
 
    /* 
     * create a socket 
     */ 
 
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 
        { 
        perror( "Failed to create socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * bind ip address and port number to socket 
     */ 
 
    if ( bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) 
        { 
        perror( "Failed to bind socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * set socket as a listen socket 
     */ 
    if ( listen(sockfd, (1) BACKLOG (2) ) < 0 ) 
        { 
        perror( "Failed to set socket passive" ); 
        exit( EXIT_FAILURE ); 
        } 
    exit( EXIT_SUCCESS ); 
} 

In this example of a listen() function:

  1. sockfd is the socket descriptor previously defined by a call to the socket() function.
  2. BACKLOG specifies that only one pending connection can be queued at any given time. The maximum number of connections is specified by the system configuration variable somaxconn . The default value for somaxconn is 1024. Refer to the Compaq TCP/IP Services for OpenVMS Tuning and Troubleshooting manual for how to display and change the somaxconn value dynamically.

2.4.2 Setting a Socket to Listen (System Services)

Example 2-6 shows how to use the IO$_SETMODE function to set the socket to listen for requests.

Example 2-6 Setting a Socket to Listen (System Services)

 
#include <descrip.h>                /* define OpenVMS descriptors           */ 
#include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */ 
#include <in.h>                     /* define internet related constants,   */ 
                                    /* functions, and structures            */ 
#include <iodef.h>                  /* define i/o function codes            */ 
#include <ssdef.h>                  /* define system service status codes   */ 
#include <starlet.h>                /* define system service calls          */ 
#include <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
#include <string.h>                 /* define string handling functions     */ 
#include <stsdef.h>                 /* define condition value fields        */ 
#include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */ 
                                    /* structures, and functions            */ 
 
 
#define BACKLOG     1                   /* server backlog                   */ 
#define PORTNUM     12345               /* server port number               */ 
 
struct iosb 
    {                                   /* i/o status block                 */ 
    unsigned short status;              /* i/o completion status            */ 
    unsigned short bytcnt;              /* bytes transferred if read/write  */ 
    void *details;                      /* address of buffer or parameter   */ 
    }; 
 
struct itemlst_2 
    {                                   /* item-list 2 descriptor/element   */ 
    unsigned short length;              /* length                           */ 
    unsigned short type;                /* parameter type                   */ 
    void *address;                      /* address of item list             */ 
    }; 
 
struct sockchar 
    {                                   /* socket characteristics           */ 
    unsigned short prot;                /* protocol                         */ 
    unsigned char type;                 /* type                             */ 
    unsigned char af;                   /* address format                   */ 
    }; 
 
 
int main( void ) 
{ 
    struct iosb iosb;                   /* i/o status block                 */ 
    unsigned int status;                /* system service return status     */ 
    unsigned short channel;             /* network device i/o channel       */ 
    struct sockchar sockchar;           /* socket characteristics buffer    */ 
    struct sockaddr_in addr;            /* socket address structure         */ 
    struct itemlst_2 addr_itemlst;      /* socket address item-list         */ 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */ 
 
    /* 
     * initialize socket characteristics 
     */ 
 
    sockchar.prot = TCPIP$C_TCP; 
    sockchar.type = TCPIP$C_STREAM; 
    sockchar.af   = TCPIP$C_AF_INET; 
 
    /* 
     * initialize socket address item-list descriptor 
     */ 
 
    addr_itemlst.length  = sizeof( addr ); 
    addr_itemlst.type    = TCPIP$C_SOCK_NAME; 
    addr_itemlst.address = &addr; 
 
    /* 
     * initialize socket address structure 
     */ 
 
    memset( &addr, 0, sizeof(addr) ); 
    addr.sin_family      = TCPIP$C_AF_INET; 
    addr.sin_port        = htons( PORTNUM ); 
    addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; 
 
    /* 
     * assign i/o channel to network device 
     */ 
 
    status = sys$assign( &inet_device,      /* device name                  */ 
                         &channel,          /* i/o channel                  */ 
                         0,                 /* access mode                  */ 
                         0                  /* not used                     */ 
                       ); 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to assign i/o channel\n" ); 
        exit( status ); 
        } 
 
    /* 
     * create a socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &sockchar,           /* p1 - socket characteristics  */ 
                       0,                   /* p2                           */ 
                       0,                   /* p3                           */ 
                       0,                   /* p4                           */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to create socket\n" ); 
        exit( status ); 
        } 
 
    /* 
     * bind ip address and port number to socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       &addr_itemlst,       /* p3 - local socket name       */ 
                       0,                   /* p4                           */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to bind socket\n" ); 
        exit( status ); 
        } 
 
    /* 
     * set socket as a listen socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       0,                   /* p3                           */ 
                       BACKLOG,             /* p4 - connection backlog      */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to set socket passive\n" ); 
        exit( status ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 

Note

Although you can use separate $QIO calls for socket create, bind, and listen operations, you can also perform these operations with one $QIO call.

2.5 Initiating a Connection (TCP Protocol)

A TCP client establishes a connection with a TCP server by issuing the connect() function. The connect() function initiates a three-way handshake between the client and the server. This must be successful to establish the connection.

2.5.1 Initiating a Connection (Sockets API)

To initiate a connection to a a TCP server, use the connect() function. Example 2-7 shows a TCP client using the connect() function to initiate a connection to a TCP server.

Example 2-7 Initiating a Connection (Sockets API)

 
#include <in.h>                     /* define internet related constants,   */ 
                                    /* functions, and structures            */ 
#include <inet.h>                   /* define network address info          */ 
#include <netdb.h>                  /* define network database library info */ 
#include <socket.h>                 /* define BSD socket api                */ 
#include <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
#include <string.h>                 /* define string handling functions     */ 
 
 
#define BUFSZ       1024                /* user input buffer size           */ 
#define PORTNUM     12345               /* server port number               */ 
 
 
void get_servaddr( void *addrptr ) 
{ 
    char buf[BUFSIZ]; 
    struct in_addr val; 
    struct hostent *host; 
 
    while ( TRUE ) 
        { 
        printf( "Enter remote host: " ); 
 
        if ( fgets(buf, sizeof(buf), stdin) == NULL ) 
            { 
            printf( "Failed to read user input\n" ); 
            exit( EXIT_FAILURE ); 
            } 
 
        buf[strlen(buf)-1] = 0; 
 
        val.s_addr = inet_addr( buf ); 
 
        if ( val.s_addr != INADDR_NONE ) 
            { 
            memcpy( addrptr, &val, sizeof(struct in_addr) ); 
            break; 
            } 
 
        if ( (host = gethostbyname(buf)) ) 
            { 
            memcpy( addrptr, host->h_addr, sizeof(struct in_addr) ); 
            break; 
            } 
        } 
} 
 
 
int main( void ) 
{ 
    int sockfd; 
    struct sockaddr_in addr; 
 
    /* 
     * initialize socket address structure 
     */ 
 
    memset( &addr, 0, sizeof(addr) ); 
    addr.sin_family = AF_INET; 
    addr.sin_port   = htons( PORTNUM ); 
    get_servaddr( &addr.sin_addr ); 
 
    /* 
     * create a socket 
     */ 
 
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 
        { 
        perror( "Failed to create socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * connect to specified host and port number 
     */ 
 
    printf( "Initiated connection to host: %s, port: %d\n", 
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) 
          ); 
 
    if ( connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) 
        { 
        perror( "Failed to connect to server" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 


Previous Next Contents Index