Example 4-12 IO$_WRITEVBLK Function (MACRO-32 Programming)
.title write .ident /01/ ; ; Write a vectored buffer ; $inetsymdef ; INET symbols dev: .ascid /ucx$device:/ ; INET device name channel: .word 0 ; INET channel iostatus: .quad 0 ; I/O status block ; ; INET Socket address definition of the remote host ; Ret_adr: .word INET$C_AF_INET ; INET family .word 5002 ; Port number ; Remote host IP address .byte 128,20,20 ; Network/subnetwork number .byte 156 ; Remote Host number .blkb 8 Ret_len=.-Ret_adr leng: .long 0 ; Return length of Remote IP address ; ; INET Socket address definition of the local host ; Local_adr: .word INET$C_AF_INET ; INET family .word 5001 ; Port number ; Local host IP address .byte 128,20,20 ; Network/subnetwork number .byte 10 ; Local Host number .blkb 8 par11: .word INET$C_UDP ; UDP/IP protocol .word INET_PROTYP$C_DGRAM ; Datagram type of socket ; ; Item_list_2 descriptor for the Remote IP address ; par12: .long ret_len ; Length .address ret_adr ; Buffer address ; ; Item_list_2 descriptor for the Local IP address ; par13: .long ret_len ; Length .address local_adr ; Address ; ; I/O Buffer ; buffer: .blkb 512 buflen=.-buffer .entry start,^m<> . . . ; ; Perform a QIOW write operation ; write: $qiow_s efn=#31,- ; Event flag chan=channel, - ; Channel func=#io$_writevblk,- ; I/O function iosb= iostatus,- ; I/O status p1=buffer,- ; I/O Buffer address p2=#buflen,- ; I/O Buffer length p3=#par12 ; Address of Descriptor ; of buffer of the remote ; Host IP address blbc r0,exit ; Branch if error movzwl iostatus,r0 ; blbc r0,exit ; $dassgn_s chan=Channel ; Deassign the socket device exit: ret ; Exit .end start
Example 4-13 IO$_WRITEVBLK Function --- Vectored (C Programming)
#module write_vecio /* **++ ** ** This example does vectored buffers write ** **-- */ /* ** INCLUDE FILES */ #include <descrip.h> #include <ucx$inetdef.h> /* INET symbol definitions */ #include <iodef.h> /* ** */ struct bvec /* Structure definition for vec buf */ { int lenth ; char *b_adrs ; } ; struct sockaddr { /* Structure definition for socket adrs */ short inet_family ; short inet_port ; char adrs[4] ; char blkb[8] ; } ; struct itlst { int lgth ; struct sockaddr *hst ; } ; main() { int status ; /* For return status */ short channel ; /* INET channel */ short sck_parm[2] ; /* Socket creation parameter */ int iosb [2] ; /* I/O status block */ char buf_1[12],buf_2[12],buf_3[12],buf_4[12] ; struct sockaddr remote_host ; /* Socket adrs definition for rhst */ struct sockaddr local_host ; /* Socket adrs definition for lhst */ struct itlst lhst_adrs ; struct itlst rhst_adrs ; struct bvec buf_vec[5] = { {12, &buf_1 }, {12, &buf_2 }, {12, &buf_3 }, {12, &buf_4 }, {0, 0 } } ; /* Descriptor for Inet device name */ struct dsc$descriptor dev = { 3, DSC$K_CLASS_S, DSC$K_DTYPE_T, "UCX$DEVICE:"} ; /* Descriptor for vectored buffer */ struct dsc$descriptor buf_d = { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0} ; /* Initialize the parameters */ sck_parm[0] = INET$C_UDP ; /* UDP/IP protocol */ sck_parm[1] = INET_PROTYP$C_DGRAM ; /* Datagram type of socket */ /* Itlst for local IP address */ lhst_adrs.lgth = sizeof(local_host); lhst_adrs.hst = &local_host ; rhst_adrs.lgth = sizeof(remote_host) ; rhst_adrs.hst = &remote_host ; buf_d.dsc$a_pointer = buf_vec; buf_d.dsc$w_length = sizeof (bvec) ; /* Initialize socket address for remote host */ remote_host.inet_family = INET$C_AF_INET;/* INET family */ remote_host.inet_port = 0 ; /* Port number */ remote_host.adrs[0] = 128 ; /* Network/subnetwork*/ remote_host.adrs[1] = 45 ; /* number */ remote_host.adrs[2] = 45 ; remote_host.adrs[3] = 175 ; /* Host number */ remote_host.blkb[0] = 0 ; remote_host.blkb[1] = 0 ; remote_host.blkb[2] = 0 ; remote_host.blkb[3] = 0 ; remote_host.blkb[4] = 0 ; remote_host.blkb[5] = 0 ; remote_host.blkb[6] = 0 ; remote_host.blkb[7] = 0 ; /* Initialize socket address for local host */ local_host.inet_family = INET$C_AF_INET ;/* INET family */ local_host.inet_port = 0 ; /* Port number */ local_host.adrs[0] = 128 ; /* Network/subnetwork*/ local_host.adrs[1] = 45 ; /* number */ local_host.adrs[2] = 45 ; local_host.adrs[3] = 186 ; /* Host number */ local_host.blkb[0] = 0 ; local_host.blkb[1] = 0 ; local_host.blkb[2] = 0 ; local_host.blkb[3] = 0 ; local_host.blkb[4] = 0 ; local_host.blkb[5] = 0 ; local_host.blkb[6] = 0 ; local_host.blkb[7] = 0 ; /* ** Assign a channel to INET device */ status = SYS$ASSIGN( &dev, &channel, 0, 0) ; if ((status & 1) == 0) { printf("Failed to assign channel to INET device \n") ; return(status) ; } /* ** Create and bind the device socket to local host */ status = SYS$QIOW( 31, /* Event flag */ channel, /* Channel number */ IO$_SETMODE, /* I/O function */ iosb, /* I/O status block */ 0, 0, &sck_parm, /* P1 Socket creation parameter */ 0, &lhst_adrs, /* P3 Socket bind parameter */ 0,0,0) ; if ((status & 1) == 0) { printf("Failed to create and bind the device socket \n") ; return(status) ; } /* ** Perform the QIO write operation */ status = SYS$QIOW( 31, /* Event flag */ channel, /* Channel number */ IO$_WRITEVBLK,/* I/O function */ iosb, /* I/O status block */ 0, 0, 0, 0, &rhst_adrs, /* P3 Remote host adrs desc */ 0, &buf_d, /* P5 Vectored buffer desc */ 0) ; if ((status & 1) == 0) { printf("Failed to write to socket \n") ; return(status) ; } /* ** Deassign the INET dev channel */ SYS$DASSGN (channel); return(status) ; }
Example 4-14 IO$_WRITEVBLK Function (C Programming)
#module write_io /* **++ ** ** This example does writes to INET device ** **-- */ /* ** INCLUDE FILES */ #include <descrip.h> #include <ucx$inetdef.h> /* INET symbol definitions */ #include <iodef.h> struct sockaddr { /* Structure definition for socket adrs */ short inet_family ; short inet_port ; char adrs[4] ; char blkb[8] ; } ; struct itlst { int lgth ; struct sockaddr *hst ; } ; main() { int status ; /* For return status */ short channel /* INET channel */ short sck_parm[2] ; /* Socket creation parameter */ int iosb [2] ; /* I/O status block */ struct sockaddr local_host ; /* Socket adrs definition for lhst */ struct itlst lhst_adrs ; char buf[128] ; int buflen = 128 ; /* Descriptor for Inet device name */ struct dsc$descriptor dev = { 3, DSC$K_CLASS_S, DSC$K_DTYPE_T, "UCX$DEVICE:"} ; /* Initialize the parameters */ sck_parm[0] = INET$C_UDP ; /* UDP/IP protocol */ sck_parm[1] = INET_PROTYP$C_DGRAM ; /* Datagram type of socket */ /* Itlst for local IP address */ lhst_adrs.lgth = sizeof(local_host); lhst_adrs.hst = &local_host ; /* ** Assign a channel to INET device */ status = SYS$ASSIGN( &dev, &channel, 0, 0) ; if ((status & 1) == 0) { printf("Failed to assign channel to INET device \n") ; return(status) ; } /* Initialize socket address for local host */ local_host.inet_family = INET$C_AF_INET ;/* INET family */ local_host.inet_port = 0 ; /* Port number */ local_host.adrs[0] = 128 ; /* Network/subnetwork*/ local_host.adrs[1] = 45 ; /* number */ local_host.adrs[2] = 45 ; local_host.adrs[3] = 216 ; /* Host number */ local_host.blkb[0] = 0 ; local_host.blkb[1] = 0 ; local_host.blkb[2] = 0 ; local_host.blkb[3] = 0 ; local_host.blkb[4] = 0 ; local_host.blkb[5] = 0 ; local_host.blkb[6] = 0 ; local_host.blkb[7] = 0 ; /* ** Create and bind the device socket to local host */ status = SYS$QIOW( 31, /* Event flag */ channel, /* Channel number */ IO$_SETMODE, /* I/O function */ iosb, /* I/O status block */ 0, 0, &sck_parm, /* P1 Socket creation parameter */ 0, &lhst_adrs, /* P3 Socket bind parameter */ 0,0,0) ; if ((status & 1) == 0) { printf("Failed to create and bind the device socket \n") ; return(status) ; } /* ** Perform the QIO write operation */ status = SYS$QIOW( 0, /* Event flag */ channel, /* Channel number */ IO$_WRITEVBLK,/* I/O function */ iosb, /* I/O status block */ 0, 0, buf, /* P1 buffer */ buflen,0,0,0,0);/* P2 buffer length */ if ((status & 1) == 0) { printf("Failed to write to INET device \n") ; return(status) ; } /* ** Deassign the INET dev channel */ SYS$DASSGN (channel); return(status) ; }
This chapter contains information to help you increase the portability of the internet application programs that you write for the DIGITAL TCP/IP Services for OpenVMS software.
For more information on writing socket programs, see the OpenVMS
Run-Time Library (RTL) for DEC C Reference manual.
5.1 Internet Protocols
The IP (Internet Protocol) family is a collection of protocols on the
Transport layer that use the internet address format. This section
describes TCP (Transmission Control Protocol) and UDP (User Datagram
Protocol) sockets.
5.1.1 TCP Sockets
TCP provides reliable, flow-controlled, two-way transmission of data. TCP is a byte-stream protocol used to support the SOCK_STREAM abstraction. TCP uses the standard IP address format and provides a per-host collection of port addresses. Thus, each address consists of an internet address specifying the host and network, with a specific TCP port on the host identifying the peer entity.
Sockets using TCP are either active or passive. The following table lists the differences between these socket types.
Socket Type | Description |
---|---|
Active sockets | Initiate connections to passive sockets. By default, TCP sockets are created active. |
Only active sockets can use the connect() call to initiate connections. | |
Passive sockets | To create a passive socket, use the listen() system call after binding the socket with the bind() system call. |
Only passive sockets can use the accept() call to accept incoming connections. | |
Passive sockets may underspecify their location to match incoming connection requests from multiple networks. This technique, called wildcard addressing, allows a single server to provide service to clients on multiple networks. |
Create a socket that listens to all hosts on any network, as follows:
TCP supports one socket option set with the setsockopt() and tested with getsockopt. Under most circumstances, TCP sends data when it is presented. When outstanding data has not been acknowledged, TCP gathers small amounts of output and sends it in a single packet when an acknowledgment is received.
For a small number of clients, such as window systems that send a
stream of mouse events that receive no replies, this packetization can
cause significant delays. Therefore, TCP provides a Boolean option,
TCP_NODELAY (from <netinet/tcp.h>), to defeat
this algorithm. The option level for the setsockopt() call is
the protocol number for TCP, available from getprotobyname().
5.1.2 UDP Sockets
UDP is a protocol that supports the SOCK_DGRAM abstraction for the internet protocol family. UDP sockets are connectionless and are normally used with the sendto() and recvfrom() calls. You can also use the connect() call to fix the destination for future packets (in which case, you can use the recv() or read() or write() system calls).
UDP address formats are identical to those used by TCP. In particular,
UDP provides a port identifier in addition to the normal internet
address format. Note that the UDP port space is separate from the TCP
port space (for example, a UDP port cannot be connected to a
TCP port). Also, you can send broadcast packets (assuming the
underlying network supports this) by using a reserved broadcast
address. This address is network-interface dependent. The
SO_BROADCAST option must be set on the socket and the process
must have a privileged UIC, or SYSPRV, BYPASS, or OPER privileges for
broadcasting to succeed.
5.2 Calling a C Socket Routine from an AST State
Calls to various C Socket routines return information within a static area. The OpenVMS environment allows an asynchronous system trap (AST) routine to interrupt a C Socket routine during its execution. In addition, the ASTs of more privileged modes can interrupt ASTs of less privileged modes. Therefore, observe caution when calling a C Socket routine from an AST state while a similar C Socket routine is being called from a non-AST state or a less privileged access mode.
The C Socket routines that use a static area are:
Several C Socket routines access files in order to retrieve their information. You should not call these routines from either the KERNEL or EXEC modes when the ASTs are disabled. These C Socket routines are:
You cannot use standard I/O with sockets. The fdopen function
does not support sockets.
5.5 Event Flags
C Socket routines can use event flags during their operation. To assign
event flags, use the library routine LIB$GET_EF. The flags are released
when the routine no longer needs them.
5.6 Suppressing DEC C Compilation Warnings
Certain parameters to the DIGITAL TCP/IP Services for OpenVMS C Socket
routines require typecasting to suppress DEC C compilation
warnings. Typecasting is required because of parameter prototyping,
which the DEC C header (.h) files have in order to
comply with ANSI standards. The DIGITAL UNIX header files have
different requirements because their C Socket routines are not
parameter prototyped.
5.7 Header Files
You can include header files on a OpenVMS system without using angle brackets:
#include types
This form of the #include preprocessor directive is possible on OpenVMS systems because all header files are located in a text library in SYS$LIBRARY. On DIGITAL UNIX systems, you must specify header files with angle brackets (< >) or double quotes (" ") and subdirectories that locate a header file.
For example, to include the header file types.h, you would use the following form of the #include directive:
#include <sys/types.h>
This section describes the structures you can use when writing internet
applications for OpenVMS software.
5.8.1 hostent Structure
The hostent structure, defined in the <netdb.h> header file, specifies or obtains a host name, a list of aliases associated with the network, and the network's number as specified in an internet address from the hosts database. An entry in the hosts database is created with the following command:
UCX> SET HOST xxxx
The DIGITAL TCP/IP for OpenVMS Services Management book contains a description of the hosts database.
The hostent structure is defined as follows:
struct hostent { char *h_name;(1) /* official name of host */ char **h_aliases;(2) /* alias list */ int h_addrtype;(3) /* host address type */ int h_length;(4) /* length of address */ char **h_addr_list;(5) /* list of addresses from name server */ #define h_addr h_addr_list[0](6) /* address, for backward compatibility */ };
The members of the hostent structure are:
The in_addr structure, defined in the <in.h> header file, specifies or obtains an internet address. The address format can be any of the supported internet address notation formats. See the DIGITAL TCP/IP for OpenVMS Services Management book for information on internet address notation.
The in_addr structure is defined as follows:
struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un; #define s_addr S_un.S_addr /* can be used for most tcp & ip code */ #define s_host S_un.S_un_b.s_b2 /* host on imp */ #define s_net S_un.S_un_b.s_b1 /* network */ #define s_imp S_un.S_un_w.s_w2 /* imp */ #define s_impno S_un.S_un_b.s_b4 /* imp # */ #define s_lh S_un.S_un_b.s_b3 /* logical host */ };
On DECnet/OSI for DIGITAL UNIX systems, the iovec structure is defined in the <uio.h> header file. On OpenVMS systems, it is defined in the <socket.h> header file.
The iovec structure describes one scatter/gather buffer. Multiple scatter/gather buffer descriptors are stored as an array of iovec elements.
The iovec structure is defined as follows:
struct iovec { char *iov_base;(1) int iov_len;(2) }
The members of the iovec structure are:
The linger structure, defined in the <socket.h> header file, specifies the setting or resetting of the socket option for the time interval that the socket lingers for data. The linger structure is supported only by STREAM type sockets.
The linger structure is defined as follows:
struct linger { int l_onoff;(1) /* option on/off */ int l_linger;(2) /* linger time */ };
The members of the linger structure are:
The msghdr structure, defined in the <socket.h> header file, specifies the buffer parameter of recvmsg and sendmsg. It allows you to specify an array of scatter/gather buffers. The recvmsg parameter scatters the data to several user receive buffers. The msghdr structure gathers data from several user transmit buffers before being transmitted.
The msghdr structure is defined as follows:
struct msghdr { char *msg_name;(1) /* optional address */ int msg_namelen;(2) /* size of address */ struct iov *msg_iov;(3) /* scatter/gather array */ int msg_iovlen;(4) /* # elements in msg_iov */ char *msg_accrights;(5) /* access rights sent/received */ int msg_accrightslen;(6) };
The members of the msghdr structure are:
The netent structure, defined in the <netdb.h> header file, specifies or obtains a network name, a list of aliases associated with the network, and the network's number specified as an internet address from the network database. An entry in the network database is created with the following command:
UCX> SET NETWORK xxxx
The DIGITAL TCP/IP for OpenVMS Services Management book contains a description of the network database.
The netent structure is defined as follows:
struct netent { char *n_name;(1) /* official name of net */ char **n_aliases;(2) /* alias list */ int n_addrtype;(3) /* net address type */ long n_net;(4) /* net number */ };
The members of the netent structure are:
The sockaddr structure, defined in the <socket.h> header file, specifies a general address family.
The sockaddr structure is defined as follows:
struct sockaddr { u_short sa_family;(1) /* address family */ char sa_data[14];(2) /* up to 14 bytes of direct address */ };