Example 2-23 shows a TCP server using the MSG_OOB flag with the send() routine.
Example 2-23 Writing OOB Data Using C Socket Programming
/* This program accepts a connection on TCP port 1234, sends the string, "Hello, world!", waits two seconds, sends an urgent BEL (^G), waits another two seconds, repeats the Hello message, and terminates. */ #include <types.h> #include <in.h> #include <socket.h> #include <unixio.h> #define PORTNUM 1234 main() { struct sockaddr_in lcladdr; int r, s, one = 1; char *message = "Hello, world!\r\n", *oob_message = "\007"; lcladdr.sin_family = AF_INET; lcladdr.sin_addr.s_addr = INADDR_ANY; lcladdr.sin_port = htons(PORTNUM); if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror("socket"); if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) perror("setsockopt"); if (bind(s, &lcladdr, sizeof(lcladdr))) perror("bind"); if (listen(s, 1)) perror("listen"); if ((r = accept(s, 0, 0)) < 0) perror("accept"); if (send(r, message, strlen(message), 0) != strlen(message)) perror("send"); sleep(2); if (send(r,(1) oob_message,(2) strlen(oob_message),(3) MSG_OOB)(4) != strlen(oob_message)) perror("send"); sleep(2); if (send(r, message, strlen(message), 0) != strlen(message)) perror("send"); sleep(2); if (close(r)) perror("close"); if (close(s)) perror("close"); }
The send() routine is used to send OOB data to a remote socket, as follows:
An application that uses UDP can write to a remote host. Broadcasting means you send datagrams in one operation to all remote hosts on the local network.
If the internet pseudodevice allows broadcasting, the local host can
broadcast datagrams to all the hosts on the local network. To
broadcast, you must set the socket. The broadcast address takes the
form of a remote host address. The system manager sets up this address
on the local host for each subnet or network the host can access.
2.15 Sending a Datagram (UDP)
Client applications that use UDP can send datagrams to one or many
hosts. In both cases, specify the remote socket names.
2.15.1 Sending Datagrams with OpenVMS System Services
You can use either of the following methods to send datagrams:
To broadcast datagrams, issue a $QIO system service command with the IO$_WRITEVBLK function.
Before issuing broadcast messages, the application must issue the
IO$_SETMODE function. This sets the broadcast option in the socket. The
process must have a system UIC, and a SYSPRV, BYPASS, or OPER privilege
to issue broadcast messages. However, the system manager can disable
privilege checking with the UCX command SET PROTOCOL UDP /BROADCAST.
For more information, refer to DIGITAL TCP/IP Services for OpenVMS
Management.
2.15.3 Broadcasting Datagrams with a C Socket Interface
You can broadcast datagrams by calling the sendto() routine.
2.16 Closing and Deleting a Socket
Closing a socket means that the program can no longer transmit data. Depending on how you close the socket, the program can receive data until the peer program also closes the socket.
When a remote system closes a socket, notification is not immediate. Another thread can erroneously attempt to use the socket.
If you send data to a closed socket, you might not receive an appropriate error message. Set the UCX$FULL_DUPLEX_CLOSE socket option if you want to have your application notified of an error when it sends data on a socket that has already been closed by the peer.
When you delete a socket, all pending messages queued for transmission
are sent to the receiving socket before closing the connection.
2.16.1 Closing and Deleting with OpenVMS System Services
Make the following calls to close and delete a socket:
Example 2-24 shows a TCP client using OpenVMS system services to close and delete a socket.
Example 2-24 Closing and Deleting a Socket Using OpenVMS System Services
/* Attempt to Closet the socket. */ sysSrvSts = sys$qiow( 0, /* efn.v | 0 */ IOChannel, /* chan.v */ IO$_DEACCESS, /* func.v */ &iosb, /* iosb.r | 0 */ 0, 0, /* astadr, astprm: UNUSED */ 0, 0, 0, 0, 0, 0 /* p1 -> p6 UNUSED */ ); sys$dassgn( IOChannel );
Example 2-25 shows a TCP/IP client using the close() routine to close and delete a socket.
Example 2-25 Closing and Deleting a Socket Using C Socket Programming
#include <errno.h> #include <types.h> #include <stdio.h> #include <socket.h> #include <in.h> #include <netdb.h> /* change hostent to comply with BSD 4.3*/ #include <inet.h> #include <ucx$inetdef.h> /* INET symbol definitions */ . . . main(argc,argv) int argc; char **argv; { 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 */ /* * Close socket. */ retval = close (socket);(1) if (retval) perror ("close"); exit(); } /* end cleanup */
(1) The socket argument for the close() routine closes the socket and deletes the socket descriptor previously defined by a socket() routine.
You can shut down a socket prior to closing and deleting it. The
shutdown operation allows you to shut down communication one process at
a time. This maintains unidirectional rather than normal bidirectional
connections, allowing you to shut down communications on receive,
transmit, or both data queues. For example, if you no longer want to
transmit data but want to continue receiving data, shut down the
transmit side of the socket connection and keep open the receive side
of the connection.
2.17.1 Shutting Down a Socket with OpenVMS System Services
To shut down a socket, issue the IO$_DEACCESS function with the IO$M_SHUTDOWN modifier. This function shuts down all or part of the full-duplex connection on the device socket.
The application uses subfunctions or flags to specify whether pending I/O operations are completed or discarded before the IO$_DEACCESS function completes. After the IO$_DEACCESS function completes, messages can no longer be transmitted or received.
Example 2-26 shows a TCP server using the IO$_DEACCESS function and the IO$M_SHUTDOWN modifier to shut down all communications. In this example, no data is received or transmitted and all queued data is discarded.
Example 2-26 Shutting Down a Socket Using OpenVMS System Services
/* ** ** Shutdown this server. ** */ sysSrvSts = sys$qiow( 0, /* efn.v | 0 */ IOChannel, /* chan.v */ IO$_DEACCESS | IO$M_SHUTDOWN, /* func.v */ &iosb, /* iosb.r | 0 */ 0, 0, /* astadr, astprm: UNUSED */ 0, 0, 0, /* p1, p2, p3 UNUSED */ UCX$C_DSC_ALL, /* p4.v mode to shutdown */ 0, 0 /* p5, p6 UNUSED */ ); if((( sysSrvSts & 1 ) != 1 ) || /* Validate the system service status. */ (( iosb.cond_value & 1 ) != 1)) /* Validate the IO status. */ errorExit( sysSrvSts, iosb.cond_value ); else printf( " SUCCEEDED in shutting down this server.\n" ); sys$dassgn( IOChannel );
Example 2-27 shows a TCP/IP client using the shutdown() routine.
Example 2-27 Shutting Down a Socket Using C Socket Programming
#include <errno.h> #include <types.h> #include <stdio.h> #include <socket.h> #include <in.h> #include <netdb.h> /* change hostent to comply with BSD 4.3*/ #include <inet.h> #include <ucx$inetdef.h> /* INET symbol definitions */ . . . /* * Call cleanup to shutdown and close socket. */ cleanup(sock_1); } /* end main */ /*-----------------------------------------------------------*/ cleanup(socket) int socket; { int retval; /* * Shutdown socket completely. */ retval = shutdown(socket(1),(2)3)(2); if (retval == -1) perror ("shutdown"); /* * Close socket. */ retval = close (socket); if (retval) perror ("close"); exit(); } /* end cleanup */
The $CANCEL system service cancels pending I/O requests on a specific channel or socket. This includes all I/O requests queued and in progress.
There is no C Socket routine for this operation. The C Socket library
functions are synchronous.
2.19 Application Development Tools for OpenVMS System Services Programming
DIGITAL provides include files, data types, and support routines to
help with OpenVMS system services programming.
2.19.1 Include Files for OpenVMS System Services Programming
The include files provide definitions for constants. The available include files are as follows:
Include File | Description |
---|---|
descrip.h | OpenVMS descriptor information |
in.h | Internet system constants and structures |
inet.h | Network address information |
iodef.h | I/O function code definitions |
lib$routines.h | Run-time library routine signatures |
netdb.h | Network database library information |
signal.h | UNIX-style signal value definitions |
socket.h | TCP/IP socket definitions |
ssdef.h | System services return status |
starlet.h | System services calls |
stdio.h | Standard UNIX I/O definitions |
stdlib.h | General utilities |
string.h | String handling function definitions |
ucx$inetdef.h | UCX network definitions |
The data types or data structures locally define unsigned entities. The following lists the available data structures.
*/ ** Locally defined data structures. /* typedef struct IosbStruct { unsigned short cond_value; unsigned short count; unsigned long info; } iosbType, /* For one occurrence */ *iosbPtr; /* For a pointer to an occurrence */ typedef struct SocketParamStruct { unsigned short protocol; unsigned char type; unsigned char family; } socketParamType, /* For one occurrence */ *socketParamPtr; /* For a pointer to an occurrence*/ /* ** ** IP Address information. ** */ typedef struct IPAddrInfoStruct { unsigned int length; char *address; unsigned int *retLenPtr; } iPAddrInfoType, /* For one occurrence */ *iPAddrInfoPtr; /* For a pointer to an occurrence*/ /* ** ** Item List structure for getting and setting socket options. ** */ typedef struct ILSockOptStruct { unsigned short length; unsigned short code; char *optStructAddr; } iLSockOptType, /* For one occurrence */ *iLSockOptPtr, /* For a pointer to an occurrence*/ iLSockOptArr[]; /* For an array of occurrences*/ /* ** ** Set socket options structure. ** */ typedef struct SetSockOptStruct { unsigned short length; unsigned short code; char *optBuffAddr; } setSockOptType, /* For one occurrence */ *setSockOptPtr, /* For a pointer to an occurrence*/ setSockOptArr[]; /* For an array of occurrences*/ /* ** ** Get socket options structure. ** */ typedef struct GetSockOptStruct { unsigned short length; unsigned short code; char *optBuffAddr; int *retLength; } getSockOptType, /* For one occurrence */ *getSockOptPtr, /* For a pointer to an occurrence*/ getSockOptArr[]; /* For an array of occurrences*/ /* /* ** ** MACRO DEFINITIONS ** */ ** */ #define MaxBuff 80 #define SERVER_PORT_NUMBER 5321 #define SERVER_QLENGTH 4
The support routines provide two functions. One routine closes and deassigns the socket from the network device. The other routine signals errors and exits. The contents of the support routines are as follows:
(1) ** FUNCTION: cleanup() ** ** Close the socket and deassign it from the network device. ** ** RETURNS: none ** */ static void cleanup( int IOChannel ) { iosbType iosb; /* I/O result status */ int sysSrvSts; /* System Service status */ /* Attempt to Closet the socket. */ sysSrvSts = sys$qiow( 0, /* efn.v | 0 */ IOChannel, /* chan.v */ IO$_DEACCESS, /* func.v */ &iosb, /* iosb.r | 0 */ 0, 0, /* astadr, astprm: UNUSED */ 0, 0, 0, 0, 0, 0 /* p1 -> p6 UNUSED */ ); sys$dassgn( IOChannel ); } /* END cleanup() */ (2) ** FUNCTION: errorExit() ** ** Signal any errors and exit. ** ** RETURNS: none ** */ static void errorExit( int sysSrvSts, /* System Service status */ unsigned short iosbCond ) /* I/O result status */ { if(( sysSrvSts & 1 ) != 1 ) /* Validate the system service status. */ lib$signal( sysSrvSts ); if(( iosbCond & 1 ) != 1 ) /* Validate the IO status. */ lib$signal( iosbCond ); exit( SS$_NORMAL ); } /* END errorExit() */
The examples in this chapter were written to use the VAX C compiler but should also be compatible with the DEC C compiler. However, if you are using the DEC C or C++ compiler and are having difficulty compiling some of these programs, DIGITAL recommends using either the VAX C compiler or the DEC C or C++ compiler with the following qualifiers:
$ /STANDARD=VAXC/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES
If you compile your program using DEC C, issue the LINK command as follows:
$ LINK MAIN
Do not specify SYS$LIBRARY:UCX$IPC.OLB because the DEC C compiler does
not use this library. Also, you do not need to specify UCX$IPC_SHR
because the DEC C compiler uses this shareable image by default.
2.20.2 Linking Programs Compiled by VAX C
If you compile your program using VAX C, issue the LINK command as follows:
$ LINK MAIN, SYS$LIBRARY:UCX$IPC/LIB, SYS$INPUT/OPTIONS SYS$SHARE:UCX$IPC_SHR/SHARE
Use the /OPTIONS qualifier for executable images. UCX$IPC.OLB contains the transfer vectors used to resolve the socket routine references to the VAXCRTL.
This chapter describes how to use the $QIO system service and its data structures with DIGITAL TCP/IP Services for OpenVMS.
After you create an internet pseudodevice and assign a channel to it,
use the $QIO system service for I/O operations.
3.1 $QIO System Service Variations
The two variations of the $QIO system service are:
The only difference between the $QIO and $QIOW service calls is the
service name. The service call parameters are the same.
3.2 $QIO Syntax
The $QIO system service has the following syntax:
SYS$QIO [efn],chan,func[,iosb] [,astadr][,astprm][,p1][,p2] [,p3][,p4][,p5][,p6]
Table 3-1 describes each argument.
Argument | Description |
---|---|
efn | Event flag number |
chan | I/O channel |
func | Internet pseudodevice function code and modifier |
iosb | I/O status block |
astadr | AST (asynchronous system trap) service routine |
astprm | AST parameter to be passed |
p1, p2, p3, p4, p5, p6 | Function-dependent $QIO parameters |
3.2.1 $QIO Function-Dependent Parameters
Table 3-2 contains the symbol definitions for the $QIO arguments
p1 through p6. Use the standard mechanism for the
programming language you are using to include these symbol definitions
in your program.
File Name | Language |
---|---|
UCX$INETDEF.H | DEC C or VAX C |
UCX$INETDEF.FOR | VAX Fortran |
UCX$INETDEF.PAS | VAX PASCAL |
UCX$INETDEF.MAR | MACRO-32 |
UCX$INETDEF.PLI | VAX PL/1 |
UCX$INETDEF.R32 | BLISS-32 |
UCX$INETDEF.ADA | VAX ADA |
UCX$INETDEF.BAS | VAX BASIC |
Table 3-3 lists the $QIO functions commonly used in internet applications.
Note
The IO$_SETMODE and IO$_SETCHAR service calls function identically. All references to the IO$_SETMODE system call, its arguments, options, modifiers, and condition values returned also apply to the IO$_SETCHAR system call, which is not explicitly described in this book.
Function | Description |
---|---|
QIO$(IO$_SETMODE) QIO$(IO$_SETCHAR) | Creates the socket by setting the internet domain, protocol (socket) type, and protocol of the device socket. |
Binds a name (local address and port) to the socket. | |
Defines an internet pseudodevice as a listener on a TCP/IP server. | |
Specifies socket options. | |
QIO$(IO$_ACCESS) | Initiates a connection request by a client to a remote host TCP/IP. |
Specifies the peer where you can send datagrams. | |
Accepts a connection request from a TCP/IP client when used with the IO$M_ACCEPT modifier. | |
QIO$(IO$_WRITEVBLK) | Writes data (virtual block) from local host to remote host for stream sockets, datagrams, and raw IP. |
QIO$(IO$_READVBLK) | Reads data (virtual block) from remote host to local host for TCP/IP, UDP/IP, or IP layers. |
QIO$(IO$_DEACCESS) | Disconnects the link established between two communication agents through an ACCESS function TCP/IP. |
Shuts down the communication link when used with the IO$M_SHUTDOWN modifier. You can shut down the receive, transmit, or both portions of the link. | |
QIO$(IO$_SENSEMODE) | Obtains socket information. |
You pass two types of arguments with $QIO system services:
function-independent arguments and function-dependent arguments. The
following sections provide information on $QIO system service arguments.
3.4.1 Device- and Function-Independent $QIO Arguments
Table 3-4 describes the device- and function-independent $QIO arguments.
Argument | Description |
---|---|
efn | A longword value of the event flag number that the $QIO system service sets when the I/O operation completes. |
chan | A word value that contains the number of the I/O channel. The $QIO system service uses only the low-order word. |
func |
A longword value that specifies the internet pseudodevice functions and
function modifiers that define the specified operation.
Function modifiers affect the operation of a specified function. In MACRO-32, you use the exclamation point (!) to separate the function and the modifier. In DEC C, you use the vertical bar (|). This book uses the vertical bar (|) in text. |
(iosb) | The I/O status block that receives the final status message for the I/O operation. The iosb argument is the address of the quadword I/O status block. |
astadr | Address of the asynchronous system trap (AST) routine to be executed when the I/O operation is completed. |
astprm | Longword value containing the value to be passed to the AST routine. |