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


Previous Contents Index

2.5.2 Initiating a Connection (System Services)

To initiate a connection to a TCP server, use 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 points to the remote socket name.

Example 2-8 shows a TCP client using the IO_$ACCESS function to initiate a connection.

Example 2-8 Initiating a Connection (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 <inet.h>                   /* define network address info          */ 
#include <iodef.h>                  /* define i/o function codes            */ 
#include <netdb.h>                  /* define network database library info */ 
#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 BUFSZ       1024                /* user input buffer size           */ 
#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                   */ 
    }; 
 
 
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 ) 
{ 
    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 ); 
    get_servaddr( &addr.sin_addr ); 
 
    /* 
     * 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 ); 
        } 
 
    /* 
     * 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) 
          ); 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_ACCESS,          /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       &addr_itemlst,       /* p3 - remote socket name      */ 
                       0,                   /* p4                           */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to connect to server\n" ); 
        exit( status ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 
 

2.6 Accepting a Connection (TCP Protocol)

A TCP server program must be able to accept incoming connection requests from client programs. The accept() function:

2.6.1 Accepting a Connection (Sockets API)

Example 2-9 shows how to use the accept() function.

Example 2-9 Accepting 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 SERV_BACKLOG    1               /* server backlog                   */ 
#define SERV_PORTNUM    12345           /* server port number               */ 
 
 
int main( void ) 
{ 
    int conn_sockfd;                    /* connection socket descriptor     */ 
    int listen_sockfd;                  /* listen socket descriptor         */ 
 
    unsigned int cli_addrlen;           /* returned length of client socket */ 
                                        /* address structure                */ 
    struct sockaddr_in cli_addr;        /* client socket address structure  */ 
    struct sockaddr_in serv_addr;       /* server socket address structure  */ 
 
    /* 
     * initialize client's socket address structure 
     */ 
 
    memset( &cli_addr, 0, sizeof(cli_addr) ); 
 
    /* 
     * initialize server's socket address structure 
     */ 
 
    memset( &serv_addr, 0, sizeof(serv_addr) ); 
    serv_addr.sin_family      = AF_INET; 
    serv_addr.sin_port        = htons( SERV_PORTNUM ); 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
 
    /* 
     * create a listen socket 
     */ 
 
    if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 
        { 
        perror( "Failed to create socket" ); 
        exit( EXIT_FAILURE ); 
        } 
    /* 
     * bind server's ip address and port number to listen socket 
     */ 
 
    if ( bind(listen_sockfd, 
              (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 ) 
        { 
        perror( "Failed to bind socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * set socket as a listen socket 
     */ 
 
    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 ) 
        { 
        perror( "Failed to set socket passive" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    /* 
     * accept connection from a client 
     */ 
 
    printf( "Waiting for a client connection on port: %d\n", 
            ntohs(serv_addr.sin_port) 
          ); 
 
    cli_addrlen = sizeof(cli_addr); 
 
    conn_sockfd = accept( listen_sockfd,     (1)
                          (struct sockaddr *) &cli_addr, (2)
                          &cli_addrlen       (3)
                        ); 
    if ( conn_sockfd < 0 ) 
        { 
        perror( "Failed to accept client connection" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    printf( "Accepted connection from host: %s, port: %d\n", 
            inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) 
          ); 
 
    exit( EXIT_SUCCESS ); 
} 
 

In this example of an accept() function:

  1. listen_sockfd is the socket descriptor returned by the previous call to the socket() function. This socket is bound to an address with the bind() function. The listen() function changes the socket state from CLOSED to LISTEN (converts the unconnected socket to a passive socket).
  2. cli_addr contains the protocol address of the client.
  3. cli_addrlen is a value/result parameter that initially contains the size of the cli_addr structure. On return of the accept() function, the cli_addr structure contains the actual length, in bytes, of the socket address structure returned by the kernel for the connected socket.

2.6.2 Accepting a Connection (System Services)

To accept a connection request, use the following procedure:

  1. Use the $ASSIGN system service to create a channel for the new connection.
  2. Use the $QIO system service using the IO$_ACCESS function with the IO$M_ACCEPT function modifier.
    The p4 argument specifies the address of a word written with the channel number of the new connection. If p3 specifies a valid output buffer, the $QIO service returns the remote socket name.

    Note

    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-10 shows a TCP server using the IO$_ACCESS function with the IO$M_ACCEPT function modifier to accept incoming connection requests.

Example 2-10 Accepting a Connection (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 <inet.h>                   /* define network address info          */ 
#include <iodef.h>                  /* define i/o function codes            */ 
#include <netdb.h>                  /* define network database library info */ 
#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 SERV_BACKLOG    1               /* server backlog                   */ 
#define SERV_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 itemlst_3 
    {                                   /* item-list 3 descriptor/element   */ 
    unsigned short length;              /* length                           */ 
    unsigned short type;                /* parameter type                   */ 
    void *address;                      /* address of item list             */ 
    unsigned int *retlen;               /* address of returned length       */ 
    }; 
 
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 conn_channel;        /* connect inet device i/o channel  */ 
 
    unsigned short listen_channel;      /* listen inet device i/o channel   */ 
    struct sockchar listen_sockchar;    /* listen socket characteristics    */ 
 
    unsigned int cli_addrlen;           /* returned length of client socket */ 
                                        /* address structure                */ 
    struct sockaddr_in cli_addr;        /* client socket address structure  */ 
    struct itemlst_3 cli_itemlst;       /* client socket address item-list  */ 
 
    struct sockaddr_in serv_addr;       /* server socket address structure  */ 
    struct itemlst_2 serv_itemlst;      /* server socket address item-list  */ 
 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */ 
    /* 
     * initialize socket characteristics 
     */ 
 
    listen_sockchar.prot = TCPIP$C_TCP; 
    listen_sockchar.type = TCPIP$C_STREAM; 
    listen_sockchar.af   = TCPIP$C_AF_INET; 
 
    /* 
     * initialize client's item-list descriptor 
     */ 
 
    memset( &cli_itemlst, 0, sizeof(cli_itemlst) ); 
    cli_itemlst.length  = sizeof( cli_addr ); 
    cli_itemlst.address = &cli_addr; 
    cli_itemlst.retlen  = &cli_addrlen; 
 
    /* 
     * initialize client's socket address structure 
     */ 
 
    memset( &cli_addr, 0, sizeof(cli_addr) ); 
 
    /* 
     * initialize server's item-list descriptor 
     */ 
 
    serv_itemlst.length  = sizeof( serv_addr ); 
    serv_itemlst.type    = TCPIP$C_SOCK_NAME; 
    serv_itemlst.address = &serv_addr; 
 
    /* 
     * initialize server's socket address structure 
     */ 
 
    memset( &serv_addr, 0, sizeof(serv_addr) ); 
    serv_addr.sin_family      = TCPIP$C_AF_INET; 
    serv_addr.sin_port        = htons( SERV_PORTNUM ); 
    serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; 
 
    /* 
     * assign i/o channels to network device 
     */ 
 
    status = sys$assign( &inet_device,      /* device name                  */ 
                         &listen_channel,   /* i/o channel                  */ 
                         0,                 /* access mode                  */ 
                         0                  /* not used                     */ 
                       ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = sys$assign( &inet_device,  /* device name                  */ 
                             &conn_channel, /* i/o channel                  */ 
                             0,             /* access mode                  */ 
                             0              /* not used                     */ 
                           ); 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to assign i/o channel(s)\n" ); 
        exit( status ); 
        } 
 
    /* 
     * create a listen socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_channel,      /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &listen_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 server's ip address and port number to listen socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_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                           */ 
                       &serv_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                   */ 
                       listen_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                           */ 
                       SERV_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 ); 
        } 
 
    /* 
     * accept connection from a client 
     */ 
 
    printf( "Waiting for a client connection on port: %d\n", 
            ntohs(serv_addr.sin_port) 
          ); 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_channel,      /* i/o channel                  */ 
                       IO$_ACCESS|IO$M_ACCEPT, 
                                            /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       &cli_itemlst,        /* p3 - remote socket name      */ 
                       &conn_channel,       /* p4 - i/o channel for new     */ 
                                            /*      connection              */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to accept client connection\n" ); 
        exit( status ); 
        } 
 
    printf( "Accepted connection from host: %s, port: %d\n", 
            inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) 
          ); 
 
    exit( EXIT_SUCCESS ); 
} 
 


Previous Next Contents Index