Previous | Contents | Index |
Example 2-21 shows a TCP/IP client using the send() routine to transmit data.
Example 2-21 Writing Data Using C Socket Programming |
---|
#include <errno.h> #include <types.h> #include <stdio.h> #include <socket.h> #include <in.h> #include <netdb.h> #include <inet.h> #include <tcpip$inetdef.h> /* INET symbol definitions */ #else . . . 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 */ /* * Send message to socket 2. */ flag = 0; /* maybe 0 or MSG_OOB */ retval = send(sock_1,(1) message,(2) sizeof (message),(3) flag);(4) if (retval < 0) { perror ("oob_messsend"); shut = TRUE; } |
If your application uses TCP, you can send OOB data to a remote
process. At the remote process, the message is delivered to the user
through the data receive, or out-of-band data receive mechanisms. You
can write only one byte of OOB data at a time.
2.14.1 Writing OOB Data with OpenVMS System Services
To send out-of-band data to a remote process, issue a $QIO system service using the IO$_WRITEVBLK function with the IO$M_INTERRUPT modifier. Example 2-22 shows a TCP server using the MSG_OOB flag with the send() routine.
Example 2-22 Writing OOB Data Using OpenVMS 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 */ IO$_WRITEVBLK, /* func.v */ &iosb, /* iosb.r | 0 */ 0, 0, /* astadr, astprm: UNUSED */ &OOBBuff, /* p1.r IO buffer */ 1, /* p2.v IO buffer size */ 0, /* p3 UNUSED */ 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" ); |
To send OOB data to a remote process, use the MSG_OOB flag with the send(), sendmsg(), and sendto() routines.
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"; 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:
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 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 management command SET PROTOCOL UDP
/BROADCAST. For more information, refer to DIGITAL TCP/IP Services
for OpenVMS Management.
2.15.3 Sending Broadcast Datagrams with the C Socket Interface
You can broadcast datagrams by calling the sendto() routine.
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 $QIO(IO$_WRITEVBLK) system service routine or the sendto() C Socket routine. Make sure you include the <netinet/in.h> header file.
The system maps the specified IP destination address to the appropriate Ethernet or FDDI multicast address prior to transmitting the datagram.
You can control multicast options by specifying the following arguments to the setsockopt() system call, as appropriate:
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 is decremented to 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"); |
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 TCPIP$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 close 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> #include <inet.h> . . . 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 (sock_1);(1) if (retval) perror ("close"); exit(); } |
(1) The sock_1 argument for the close()
routine closes the socket and deletes the socket descriptor previously
defined by a socket() routine.
2.17 Shutting Down Sockets
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 */ TCPIP$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> #include <inet.h> #include <tcpip$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),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
Compaq 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 |
ioctl.h | I/O control definitions |
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 |
tcpip$inetdef.h | Network definitions |
Previous | Next | Contents | Index |