DIGITAL TCP/IP Services for OpenVMS
System Services and C Socket Programming


Previous | Contents

The following options are available at the socket level:

If you include the UCX$INETDEF definition file, you can use the options listed in Tables 6-3, 6-4, and 6-5.

Table 6-3 Communications Socket Options
Socket Option Description
UCX$C_RCVBUF Sets the socket receive quota. This option requires a system UIC, SYSPRV, BYPASS, or OPER privilege to be set.
UCX$C_SNDBUF Sets the socket send quota. This option requires a system UIC, SYSPRV, BYPASS, or OPER privilege to be set.
UCX$C_NO_RCV_CHECKSUM Disables checksum calculation for received data.
UCX$C_NO_SND_CHECKSUM Disables checksum calculation for transmitted data.
UCX$C_NO_CHECKSUM Disables checksum calculation altogether.
Unsupported socket options are ignored. You normally set and clear options with item_list descriptors.

Table 6-4 TCP/IP Options
TCP/IP Option Description
UCX$C_USELOOPBACK Shortcuts the data transfer when the transfer is local to the host. This improves the performance of the local TCP/IP transfer process and results in a lower load on the CPU when applications using local transfer are active.
UCX$C_TCP_NODELAY Specifies that the send operation will not be delayed to coalesce packets.
UCX$C_TCP_PROBE_IDLE Specifies the time interval for the KEEPALIVE probe, as well as for the connection establishing the timeout.
UCX$C_TCP_DROP_IDLE Specifies the time interval after which the connection is dropped.
UCX$C_FULL_DUPLEX_CLOSE Returns an EPIPE error (SS$_LINKDISCON) the first time data is sent after the peer has closed its half of the connection. Subsequent send operations on the half-closed socket proceeds normally.

Table 6-5 IP Options
IP Option Description
UCX$C_IP_TTL Time to live for a datagram
UCX$C_IP_TOS Type of service (1-byte value)

optval

Points to a buffer containing the parameters of the specified option.

All socket level options other than SO_LINGER should be nonzero if the option is to be enabled, or zero if it is to be disabled.

SO_LINGER uses a linger structure parameter defined in the <socket.h> file. This structure specifies the desired state of the option and the linger interval. The option value for the SO_LINGER command is the address of a linger structure. See Section 5.8.4 for a description of the linger structure.

If the socket promises reliable delivery of data and l_onoff is nonzero, the system blocks the process on the close() attempt until it is able to transmit the data or until it decides it is unable to deliver the information. A timeout period, called the linger interval, is specified in l_linger.

If l_onoff is set to zero and a close() is issued, the system processes the close in a manner that allows the process to continue as quickly as possible.

optlen

An integer containing the size of the buffer pointed to by optval.

DESCRIPTION

This routine manipulates options associated with a socket. Options can exist at multiple protocol levels. They are always present at the uppermost socket level.

When manipulating socket options, specify the level at which the option resides and the name of the option. To manipulate options at the socket level, specify level as SOL_SOCKET. To manipulate options at any other level, supply the protocol number of the appropriate protocol controlling the option. For example, to indicate that an option is to be interpreted by TCP, set the level to the protocol number (IPPROTO_TCP) of TCP. See <in.h> for the various IPPROTO values.


Return Values

0 Successful completion.
--1 Error; errno is set to indicate the error.

Errors

You can set errno to the following values:
[EBADF] The descriptor is invalid.
[ENOTSOCK] The socket descriptor references a file, not a socket.
[ENOPROTOOPT] The option is unknown.
[EFAULT] The optname parameter is not a valid part of the user address space.

vaxc$get_sdc()

Returns the socket device channel (SDC) associated with a socket descriptor for direct use with DIGITAL TCP/IP Services for OpenVMS software.

Note

This routine only works with VAX C. Use the decc$get_sdc() routine with DEC C.


Format

#include <socket.h>

short int vaxc$get_sdc (int s);


ARGUMENT

s

A socket descriptor.

DESCRIPTION

This routine returns the SDC associated with a socket. C Socket descriptors are normally used either as file descriptors or with one of the routines that takes an explicit socket descriptor as its argument. C Sockets are implemented using TCP/IP socket device channels. This routine returns the SDC used by a given socket descriptor so you can use the TCP/IP facilities directly by means of various I/O system services ($QIO).

Note

The 64-bit return from OpenVMS Alpha systems has zero-extended bits in the high 32 bits of R0.


Return Values

0 Indicates that s is not an open socket descriptor.
x The SDC number.


Chapter 7
Error Codes

This chapter contains a table of C Socket error codes and their OpenVMS system service equivalents. The C Socket routines use the DEC C compiler.

Table 7-1 Translation of Socket Error Codes to OpenVMS Error Codes
C Socket (DEC C)
Error Code
Meaning OpenVMS
System Service
Error Code
0 (success) SS$_NORMAL
1 EPERM Not owner SS$_ABORT
2 ENOENT No such file or directory SS$_ABORT
3 ESRCH No such process SS$_NOSUCHNODE
4 EINTR Interrupted system call SS$_ABORT
5 EIO I/O error SS$_ABORT
6 ENXIO No such device or address SS$_NOSUCHDEV
7 E2BIG Argument list too long SS$_ABORT
8 ENOEXEC Execution format error SS$_ABORT
9 EBADF Bad file number SS$_BADPARAM
10 ECHILD No children SS$_ABORT
11 EAGAIN No more processes SS$_ABORT
12 ENOMEM Not enough core SS$_INSFMEM
13 EACCES Permission denied SS$_ABORT
14 EFAULT Bad address SS$_ACCVIO
15 ENOTBLK Block device required SS$_ABORT
16 EBUSY Mount device busy SS$_ABORT
17 EEXIST File exists SS$_FILALRACC
18 EXDEV Cross-device link SS$_ABORT
19 ENODEV No such device SS$_ABORT
20 ENOTDIR Not a directory SS$_ABORT
21 EISDIR Is a directory SS$_ABORT
22 EINVAL Invalid argument SS$_BADPARAM
23 ENFILE File table overflow SS$_ABORT
24 EMFILE Too many open files SS$_ABORT
25 ENOTTY Not a typewriter SS$_ABORT
26 ETXTBSY Text file busy SS$_ABORT
27 EFBIG File too large SS$_ABORT
28 ENOSPC No space left on device SS$_ABORT
29 ESPIPE Illegal seek SS$_ABORT
30 EROFS Read-only file system SS$_ABORT
31 EMLINK Too many links SS$_ABORT
32 EPIPE Broken pipe SS$_LINKDISCON
33 EDOM Argument too large SS$_BADPARAM
34 ERANGE Result too large SS$_TOOMUCHDATA
35 EWOULDBLOCK Operation would block SS$_SUSPENDED
36 EINPROGRESS Operation now in progress SS$_ABORT
37 EALREADY Operation already in progress SS$_ABORT
38 ENOTSOCK Socket operation on non-socket SS$_NOTNETDEV
39 EDESTADDRREQ Destination address required SS$_NOSUCHNODE
40 EMSGSIZE Message too long SS$_TOOMUCHDATA
41 EPROTOTYPE Protocol wrong type for socket SS$_PROTOCOL
42 ENOPROTOOPT Protocol not available SS$_PROTOCOL
43 EPROTONOSUPPORT Protocol not supported SS$_PROTOCOL
44 ESOCKTNOSUPPORT Socket type not supported SS$_PROTOCOL
45 EOPNOTSUPP Operation not supported on socket SS$_ILLCNTRFUNC
46 EPFNOSUPPORT Protocol family not supported SS$_PROTOCOL
47 EAFNOSUPPORT Address family not supported SS$_PROTOCOL
48 EADDRINUSE Address already in use SS$_DUPLNAM
49 EADDRNOTAVAIL Requested address cannot be assigned SS$_IVADDR
50 ENETDOWN Network is down SS$_UNREACHABLE
51 ENETUNREACH Network is unreachable SS$_UNREACHABLE
52 ENETRESET Network dropped connection on reset SS$_RESET
53 ECONNABORTED Software caused connection abort SS$_LINKABORT
54 ECONNRESET Connection reset by peer SS$_CONNECFAIL
55 ENOBUFS No buffer space available SS$_INSFMEM
56 EISCONN Socket is already connected SS$_FILALRACC
57 ENOTCONN Socket is not connected SS$_NOLINKS
58 ESHUTDOWN Cannot send after socket shutdown SS$_SHUT
59 ETOOMANYREFS Too many references, cannot splice SS$_ABORT
60 ETIMEDOUT Connection timed out SS$_TIMEOUT
61 ECONNREFUSED Connection refused SS$_REJECT
62 ELOOP Too many levels of symbolic links SS$_ABORT
63 ENAMETOOLONG File name too long SS$_ABORT
64 EHOSTDOWN Host is down SS$_SHUT
65 EHOSTUNREACH No route to host SS$_UNREACHABLE


Appendix A
Online Program Examples

Table A-1 lists the sample programs printed in this appendix. See Table 1-1 and Table 1-2 for a complete list of all the sample programs provided online in UCX$EXAMPLES.

Table A-1 Location of Online Program Examples --- UCX$EXAMPLES:
File See...
UCX$TCP_SERVER_QIO.C Section A.1
UCX$UDP_SERVER_IPC.C Section A.2
UCX$TCP_SERVER_IPC.C Section A.3
UCX$TCP_SERVER_IPC_AUXS.C Section A.4
UCX$TCP_CLIENT_IPC.C Section A.5

A.1 TCP/IP Server Using QIO Calls

Example A-1 shows a TCP/IP server using QIO calls. You can access this file online in UCX$EXAMPLES:UCX$TCP_SERVER_QIO.C.

Depending on your compiler, you can compile and link this program in any of the following ways:

Example A-1 TCP/IP Server Using QIO Calls


 
#include <descrip.h>        /* OpenVMS descriptor information */ 
#include <errno.h>          /* UNIX style error codes for I/O routines */ 
#include <in.h>             /* Internet system constants and structures */ 
#include <inet.h>           /* Network address information */ 
#include <iodef.h>          /* I/O function code definitions */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <netdb.h>          /* Network database library information */ 
#include <signal.h>         /* UNIX style signal value definitions */ 
#include <socket.h>         /* TCP/IP socket definitions */ 
#include <ssdef.h>          /* SS$_<xyz> system service return status codes */ 
#include <starlet.h>        /* System service calls */ 
#include <stdio.h>          /* UNIX 'standard I/O' definitions   */ 
#include <stdlib.h>         /* General utilities */ 
#include <string.h>         /* String handling function definitions */ 
#include <ucx$inetdef.h>    /* UCX network definitions */ 
 
/* Convert short port number from host to network byte order */ 
#define htons(x) ((unsigned short)((x<<8)|(x>>8))) 
 
main() { 
        int     status;         /* For return status */ 
        short   channel;        /* INET channel */ 
        short   channel_1;      /* Template for ACCEPT */ 
        short   sck_parm[2];    /* Socket creation parameter */ 
        short   iosb[4];        /* I/O status block */ 
 
        char    buf[512]; 
        int     buflen = 512;   /* Buffer length */ 
        int     retval; 
        short   port; 
        unsigned char *dummy; 
        unsigned int    r_retlen; 
        int     one=1; 
        struct  SOCKADDRIN local_host, remote_host; 
 
        struct  IL2 { 
                unsigned int il2_length; 
                char *il2_address; 
        } lhst_adrs; 
 
        struct  IL3 { 
                unsigned int il3_length; 
                char *il3_address; 
                unsigned int* il3_retlen; 
        } rhst_adrs; 
 
        struct  dsc$descriptor inet_dev = 
                {10, DSC$K_CLASS_S, DSC$K_DTYPE_T, "UCX$DEVICE"}; 
 
 struct  { short len, param; int *ptr; } 
                item_list[] = {{sizeof(one), UCX$C_REUSEADDR, (int*)0 }}, 
                options = {sizeof(item_list), UCX$C_SOCKOPT, (int*)0 }; 
 
        item_list[0].ptr = &one; 
        options.ptr = (int*)item_list; 
 
        lhst_adrs.il2_length = sizeof local_host; 
        lhst_adrs.il2_address = (char *)&local_host; 
 
        rhst_adrs.il3_length  = sizeof remote_host; 
        rhst_adrs.il3_address = (char*)&remote_host; 
        rhst_adrs.il3_retlen  = &r_retlen; 
 
        sck_parm[0] = UCX$C_TCP;                    /* TCP/IP protocol */ 
        sck_parm[1] = INET_PROTYP$C_STREAM;         /* Stream type of socket */ 
        local_host.SIN$W_FAMILY = UCX$C_AF_INET;    /* INET family */ 
        local_host.SIN$L_ADDR = UCX$C_INADDR_ANY;   /* Any address */ 
 
        while (retval != 1) { 
                printf("Enter local port number:\n"); 
                retval = scanf("%hd", &port); 
                if (retval == 1) 
                        local_host.SIN$W_PORT = htons(port); 
                else scanf("%s",buf);    /* discard bad input */ 
        } 
 
        /* Assign two channels to the UCX device. */ 
        status = sys$assign(&inet_dev, &channel, 0, 0); 
        if (status & 1) 
                status = sys$assign(&inet_dev, &channel_1, 0, 0); 
        if (!(status & 1)) { 
                printf("Failed to assign channel to UCX device.\n"); 
                exit(status); 
        } 
 
       /* Create the socket and set the REUSEADDR option. */ 
       status = sys$qiow(3,             /* Event flag */ 
                        channel,        /* Channel number */ 
                        IO$_SETMODE,    /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        &sck_parm, 0,   /* P1 socket creation parameter */ 
                        0, 0, 
                        &options, 0);   /* P5 socket option descriptor */ 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to create the device socket.\n"); 
                exit(status); 
        } 
 
        /* Bind to chosen port number (after REUSEADDR is set above). */ 
        status = sys$qiow(3,            /* Event flag */ 
                        channel,        /* Channel number */ 
                        IO$_SETMODE,    /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        0, 0, 
                        &lhst_adrs,     /* P3 local socket name */ 
                        3,              /* P4 connection backlog */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to bind the device socket.\n"); 
                exit(status); 
        } 
 
        /* Accept a connection from a client. */ 
        status = sys$qiow(3,                    /* Event flag */ 
                        channel,                /* Channel number */ 
                        IO$_ACCESS|IO$M_ACCEPT, /* I/O function */ 
                        iosb,                   /* I/O status block */ 
                        0, 0, 
                        0, 0, 
                        &rhst_adrs,             /* P3 Remote IP address*/ 
                        &channel_1,             /* P4 Channel for new socket */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to accept a connection from a client.\n"); 
                exit(status); 
        } 
        dummy = (unsigned char *)&remote_host.SIN$L_ADDR; 
        printf("Connection from host: %d.%d.%d.%d, port: %d\n", 
                dummy[0], dummy[1], dummy[2], dummy[3], 
                htons(remote_host.SIN$W_PORT)); 
 
        /* Read I/O buffer. */ 
        status = sys$qiow(3,            /* Event flag */ 
                        channel_1,      /* Channel number */ 
                        IO$_READVBLK,   /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        buf,            /* P1 buffer */ 
                        buflen,         /* P2 buffer length */ 
                        0, 0, 0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                 printf("Failed to read from socket.\n"); 
 
        /* If all is well, print message */ 
        printf ("Received text: %s\n", buf); 
 
        /* Shut down the socket (optional). */ 
        status = sys$qiow(3, 
                        channel_1, 
                        IO$_DEACCESS|IO$M_SHUTDOWN, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 
                        UCX$C_DSC_ALL,    /* P4 Discard all packets */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                printf("Failed to shut down the socket.\n"); 
 
        /* Close the sockets -- accepted and listener (optional). */ 
        status = sys$qiow(3, 
                        channel_1, 
                        IO$_DEACCESS, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 0, 0, 0); 
        if (status & 1) status = sys$qiow(3, 
                        channel, 
                        IO$_DEACCESS, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 0, 0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                printf("Failed to close the socket.\n"); 
 
        /* Deassign the UCX device channels. */ 
        status = sys$dassgn(channel_1); 
        if (status & 1) status = sys$dassgn(channel); 
        if (!(status & 1)) 
        printf("Failed to deassign the channel.\n"); 
} 
 

A.2 UDP/IP Server --- C Socket Example

Example A-2 shows a UDP/IP server using the IPC socket interface. You can access this file online in UCX$EXAMPLES:UCX$UDP_SERVER_IPC.C.

This example shows you how to create a SOCK_DGRAM (UDP) socket type, bind it, and select it to receive a message on the socket. Error messages are printed to the screen.

This example is portable to UNIX. The include files are conditionally defined for both OpenVMS VAX and Alpha systems, and "perror" is used for error reporting.

The C Socket calls used in this program are:

Depending on your compiler, you can compile and link this program in any of the following ways:

Example A-2 UDP/IP Server Using the C Socket Interface


 
#ifdef VMS 
#include <descrip.h>        /* OpenVMS descriptor information */ 
#include <errno.h>          /* UNIX style error codes for I/O routines */ 
#include <in.h>             /* Internet system constants and structures */ 
#include <inet.h>           /* Network address information */ 
#include <iodef.h>          /* I/O function code definitions */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <netdb.h>          /* Network database library information */ 
#include <signal.h>         /* UNIX style signal value definitions */ 
#include <socket.h>         /* TCP/IP socket definitions */ 
#include <ssdef.h>          /* SS$_<xyz> system service return status codes */ 
#include <starlet.h>        /* System service calls */ 
#include <stdio.h>          /* UNIX 'standard I/O' definitions   */ 
#include <stdlib.h>         /* General utilities */ 
#include <string.h>         /* String handling function definitions */ 
#include <ucx$inetdef.h>    /* UCX network definitions */ 
#include <unixio.h>         /* Prototypes for UNIX emulation functions */ 
 
#else 
#include <errno.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <sys/uio.h> 
#include <time.h>  /* timeval declared here */ 
#endif 
 
 
/*-----------------------------------------------------------*/ 
 
cleanup( int socket ) 
{ 
        int    retval; 
 
        /* 
         * Shut down socket completely. 
         */ 
        retval = shutdown(socket,2); 
        if (retval == -1) 
                perror ("shutdown"); 
 
        /* 
         * Close socket. 
         */ 
        retval = close (socket); 
        if (retval) 
        perror ("close"); 
 
        exit( 1 ); 
 
} /* end cleanup */ 
 
/*--------------------------------------------------------------------*/ 
main( int argc, char **argv ) 
{ 
        int     rmask, wmask, emask; 
        int     sock_2;                         /* Socket 2  descriptor      */ 
        int     buflen,fromlen; 
        char    recvbuf[BUFSIZ]; 
static  struct  sockaddr_in sock1_name;     /* Address struct for socket1 */ 
static  struct  sockaddr_in sock2_name;     /* Address struct for socket2 */ 
        int  namelength; 
        struct  hostent         hostentstruct;  /* Storage for hostent data   */ 
        struct  hostent         *hostentptr;    /* Pointer to hostent data    */ 
        static  char            hostname[256];  /* Name of local host         */ 
        int     retval; 
        int     flag; 
        struct  timeval      timeout; 
 
        /* 
         * Check input parameters 
         */ 
        if (argc != 2 ) 
                { 
                printf("Usage: server portnumber.\n"); 
                exit( 1 ); 
                } 
 
        /* 
         * Open socket 2: AF_INET, SOCK_DGRAM. 
         */ 
        if ((sock_2 = socket (AF_INET, SOCK_DGRAM, 0)) == -1) 
                { 
                perror( "socket"); 
                exit( 1 ); 
                } 
 
 
        /* 
         * Get the local host  name. 
         */ 
        retval = gethostname(hostname,sizeof hostname); 
        if (retval) 
                { 
                perror ("gethostname"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Get pointer to network data structure for local host. 
         */ 
        if ((hostentptr = gethostbyname (hostname)) == NULL) 
                { 
                perror( "gethostbyname"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Copy hostent data to safe storage. 
         */ 
        hostentstruct = *hostentptr; 
 
 
        /* 
         * Fill in the address structure for socket 2. 
         */ 
        sock2_name.sin_family = hostentstruct.h_addrtype; 
        sock2_name.sin_port = htons(atoi(argv[1])); 
        sock2_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr); 
 
 
        /* 
         * Bind name to socket 2. 
         */ 
        retval = bind ( sock_2, 
                        (struct sockaddr*)&sock2_name, 
                        sizeof sock2_name ); 
        if (retval)                       
                { 
                perror("bind"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Select socket to receive message. 
         */ 
        emask = wmask = 0; 
        rmask = (1<<sock_2);  /* set read mask */ 
        timeout.tv_sec = 30; 
        timeout.tv_usec = 0; 
 
        retval = select( 32, &rmask, &wmask, &emask, &timeout ); 
        switch (retval) 
        { 
          case -1: 
                { 
                perror("select"); 
                cleanup(sock_2); 
                } 
          case 0: 
                { 
                printf("Select timed out with status 0.\n"); 
                cleanup(sock_2); 
                } 
          default: 
                if ((rmask & (1<<sock_2)) == 0) 
                        { 
                        printf("Select not reading on sock_2.\n"); 
                        cleanup(sock_2); 
                        } 
          } /*switch*/ 
 
 
        /* 
         * Recvfrom buffer - from sock1 on sock2. 
         */ 
 
        buflen = sizeof(recvbuf); 
        fromlen = sizeof(sock1_name); 
        flag = 0;          /* flag may be MSG_OOB and/or MSG_PEEK */ 
 
        retval = recvfrom( sock_2, 
                           recvbuf, 
                           buflen, 
                           flag, 
                           (struct sockaddr*)&sock1_name, 
                           &fromlen); 
        if (retval == -1) 
                perror("recvfrom"); 
             else 
                printf (" %s\n", recvbuf); 
 
        /* 
         * Call cleanup to shut down and close socket. 
         */ 
 
         cleanup(sock_2); 
 
  } /* end main */ 


Previous | Next | Contents