|
HP OpenVMS systems documentation |
Previous | Contents | Index |
If your application uses TCP, you can send out-of-band (OOB) data to a
remote process. At the remote process, the message is delivered to the
user through either the data receive or the OBB data receive mechanism.
You can write only 1 byte of OOB data at a time.
2.14.1 Writing OOB Data (Sockets API)
To send OOB data to a remote process, use the MSG_OOB flag with the send() , sendmsg() , and sendto() functions.
Example 2-22 shows a TCP server using the MSG_OOB flag with the send() routine.
Example 2-22 Writing OOB Data (Sockets API) |
---|
/* 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 123 main() { struct sockaddr_in lcladdr; int r, s, one = 1; char *message = "Hello, world!\r\n", *oob_message = "\007"; memset() 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:
To send out-of-band data to a remote process, use the IO$_WRITEVBLK function with the IO$M_INTERRUPT modifier. Example 2-23 shows a TCP server using the TCPIP$C_MSG_OOB flag.
Example 2-23 Writing OOB Data (System Services) |
---|
/* ** ** Attempt to send Out Of Band data to a previously established network ** connection. Use the function code of IO$_WRITEVBLK, passing the address ** of the buffer to P1, and the OOB code, TCPIP$C_MSG_OOB, to P4. ** */ OOBBuff = 7; sysSrvSts = sys$qiow( 0, /* efn.v | 0 */ IOChannel, /* chan.v */ (1) IO$_WRITEVBLK, /* func.v */ &iosb, /* iosb.r | 0 */ 0, 0, /* astadr, astprm: UNUSED */ (2) &OOBBuff, /* p1.r IO buffer */ 1, /* p2.v IO buffer size */ 0, /* p3 UNUSED */ (3) TCPIP$C_MSG_OOB, /* p4.v IO options flag */ 0, 0 /* p5, p6 UNUSED */ ); if((( sysSrvSts & 1 ) != 1 ) || /* Validate the system service status. */ (( iosb.cond_value & 1 ) != 1)) /* Validate the IO status. */ { cleanup( IOChannel ); errorExit( sysSrvSts, iosb.cond_value ); } else if( iosb.count == 0 ) printf( " FAILED to send the OOB message, no connection.\n" ); else printf( " SUCCEEDED in sending the OOB message.\n" ); |
This example writes the data that is in the buffer.
An application that uses UDP can send a datagram to a remote host, send broadcast datagrams to multiple remote hosts, or send multicast datagrams to members of a group.
With broadcasting, you send datagrams in one operation to multiple
remote hosts on the specified subnetwork. With multicasting, you send
datagrams in one operation to all hosts that are members of a
particular group. The member hosts can be located on the local network
or on remote networks, as long as the routers are configured to support
multicasting.
2.15.1 Sending Datagrams (System Services)
You can use either of the following methods to send datagrams:
You can broadcast datagrams by calling the
sendto()
function.
2.15.3 Sending Broadcast Datagrams (System Services)
To broadcast datagrams, use a $QIO system service command with the IO$_WRITEVBLK routine.
Before issuing broadcast messages, the application must issue the
IO$_SETMODE function. This sets the broadcast option in the socket. The
process must have SYSPRV, BYPASS, or OPER privilege to issue broadcast
messages. However, the system manager can disable privilege checking by
using the management command SET PROTOCOL UDP /BROADCAST. For more
information, refer to the HP TCP/IP Services for OpenVMS Management Command Reference guide.
2.15.4 Sending Multicast Datagrams
To send IP multicast datagrams, specify the IP destination address in the range of 224.0.0.0 to 239.255.255.255 using the IO$_WRITEVBLK routine or the sendto() Sockets API function. Make sure you include the IN.H header file.
The system maps the specified IP destination address to the appropriate Ethernet or FDDI multicast address before it transmits the datagram.
You can control multicast options by specifying the following arguments to the setsockopt() Sockets API, or the IO$SETMODE system service.
Value | Result |
---|---|
0 | Restricts distribution to applications running on the local host. |
1 | Forwards the multicast datagram to hosts on the local subnet. |
1---255 | With a multicast router attached to the sending host's network, forwards multicast datagrams beyond the local subnet. |
Multicast routers forward the datagram to known networks that have hosts belonging to the specified multicast group. The TTL value is decremented by each multicast router in the path. When the TTL value reaches 0, the datagram is no longer forwarded. |
u_char ttl; ttl=2; if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) perror("setsockopt"); |
int sock; struct in_addr ifaddress; char *if_to_use = "16.141.64.251"; . . . ifaddress.s_addr = inet_addr(if_to_use); if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &ifaddress, sizeof(ifaddress)) == -1) perror ("error from setsockopt IP_MULTICAST_IF"); else printf ("new interface set for sending multicast datagrams\n"); |
u_char loop=0; if (setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop sizeof(loop)) == -1) perror("setsockopt"); |
For a complete list of socket options, see Appendix A.
2.16 Using the Berkeley Internet Name Domain Service
The Berkeley Internet Name Domain (BIND) service is a host name and address lookup service for the Internet. If BIND is enabled on your system, you can make a call to the BIND resolver to obtain host names and addresses.
Typically, you make a call to the BIND resolver either before you bind
a socket or before you make a connection to a socket. You can also use
this service to translate either the local or remote host name to an
address before making a connection.
2.16.1 BIND Lookups (Sockets API)
If the BIND resolver is enabled on your system and the host name is not found in the local database, you can use either of the following functions to search the BIND database:
The host record contains both name and address information.
Example 2-24 shows how to use the gethostname() , gethostbyname() , and gethostbyaddr() functions to find a local host name and address.
Example 2-24 BIND Lookup (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 <stdio.h> /* define standard i/o functions */ #include <stdlib.h> /* define standard library functions */ int main( void ) { char host[1024]; struct in_addr addr; struct hostent *hptr; /* * get name of local host */ if ( (gethostname(host, sizeof(host))) < 0 ) (1) { perror( "Failed to get host's local name" ); exit( EXIT_FAILURE ); } printf( "Local hostname: %s\n", host ); /* * lookup local host record by name */ if ( !(hptr = gethostbyname(host)) ) (2) { perror( "Failed to find record for local host" ); exit( EXIT_FAILURE ); } addr.s_addr = *(int *) hptr->h_addr; printf( "Official hostname: %s address: %s\n", hptr->h_name, inet_ntoa(addr) ); /* * lookup local host record by address */ hptr = gethostbyaddr( &addr.s_addr, sizeof(addr.s_addr), AF_INET ); (3) if ( !hptr ) { perror( "Failed to find record for local host" ); exit( EXIT_FAILURE ); } printf( "Back-translated hostname: %s\n", hptr->h_name ); exit( EXIT_SUCCESS ); } |
In this example, the following functions and arguments were used to find a local host name and address:
If BIND is enabled on your system, the IO$_ACPCONTROL system service searches the BIND database for the host name if it does not find the name in the local host database.
Example 2-25 shows how to use OpenVMS system services to find a host name and address.
Example 2-25 BIND Lookup (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 */ 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 acpfunc { /* acp subfunction */ unsigned char code; /* subfunction code */ unsigned char type; /* call code */ unsigned short reserved; /* reserved (must be zero) */ }; int main( void ) { char host[1024]; char hostent[2048]; struct in_addr addr; struct hostent *hptr; struct iosb iosb; /* i/o status block */ unsigned int status; /* system service return status */ unsigned short channel; /* network device i/o channel */ (1) struct acpfunc func_byaddr = /* acp gethostbyaddr function code */ { INETACP_FUNC$C_GETHOSTBYADDR, INETACP$C_HOSTENT_OFFSET, 0 }; struct acpfunc func_byname = /* acp gethostbyname function code */ { INETACP_FUNC$C_GETHOSTBYNAME, INETACP$C_HOSTENT_OFFSET, 0 }; struct dsc$descriptor p1_dsc = /* acp function descriptor */ { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; struct dsc$descriptor p2_dsc = /* acp p2 argument descriptor */ { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; struct dsc$descriptor p4_dsc = /* acp p4 argument descriptor */ { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of network pseudodevice */ /* * get name of local host */ if ( (gethostname(host, sizeof(host))) < 0 ) { perror( "Failed to get host's local name" ); exit( EXIT_FAILURE ); } printf( "Local hostname: %s\n", host ); /* * 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 ); } /* * lookup local host record by name */ (2) p1_dsc.dsc$w_length = sizeof(func_byname); p1_dsc.dsc$a_pointer = (char *) &func_byname; p2_dsc.dsc$w_length = strlen( host ); p2_dsc.dsc$a_pointer = host; p4_dsc.dsc$w_length = sizeof(hostent); p4_dsc.dsc$a_pointer = hostent; (3) status = sys$qiow( EFN$C_ENF, /* event flag */ channel, /* i/o channel */ IO$_ACPCONTROL, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &p1_dsc, /* p1 - acp subfunction code */ &p2_dsc, /* p2 - hostname to lookup */ &p4_dsc.dsc$w_length,/* p3 - return length address */ &p4_dsc, /* p4 - output buffer address */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to find record for local host\n" ); exit( status ); } hptr = (struct hostent *) hostent; hptr->h_name += (unsigned int) hptr; *(char **) &hptr->h_addr_list += (unsigned int) hptr; *(char **) hptr->h_addr_list += (unsigned int) hptr; addr.s_addr = *(int *) hptr->h_addr; printf( "Official hostname: %s address: %s\n", hptr->h_name, inet_ntoa(addr) ); /* * lookup local host record by address */ p1_dsc.dsc$w_length = sizeof(func_byaddr); p1_dsc.dsc$a_pointer = (char *) &func_byaddr; p2_dsc.dsc$w_length = strlen( inet_ntoa(addr) ); p2_dsc.dsc$a_pointer = inet_ntoa( addr ); p4_dsc.dsc$w_length = sizeof(hostent); p4_dsc.dsc$a_pointer = hostent; (4) status = sys$qiow( EFN$C_ENF, /* event flag */ channel, /* i/o channel */ IO$_ACPCONTROL, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &p1_dsc, /* p1 - acp subfunction code */ &p2_dsc, /* p2 - ip address to lookup */ &p4_dsc.dsc$w_length,/* p3 - return length address */ &p4_dsc, /* p4 - output buffer address */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to find record for local host\n" ); exit( status ); } hptr = (struct hostent *) hostent; hptr->h_name += (unsigned int) hptr; printf( "Back-translated hostname: %s\n", hptr->h_name ); /* * deassign i/o channel to network device */ status = sys$dassgn( channel ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to deassign i/o channel\n" ); exit( status ); } exit( EXIT_SUCCESS ); } |
This example looks up nodes by either host name or IP address.
Previous | Next | Contents | Index |