Previous | Contents | Index |
The examples in this manual were written using the Compaq C compiler. To compile and link your program, enter the following commands:
$ CC MAIN.C/PREFIX=ALL $ LINK MAIN.OBJ |
To compile and link your Compaq C program using BSD Version 4.4, enter the following commands, where filename is the name of your program:
$ CC/PREFIX=ALL/DEFINE=(_SOCKADDR_LEN) filename.C $ LINK/MAP filename |
Instead of using the /DEFINE=(_SOCKADDR_LEN) option to the compile command, you can change your code to include the following #DEFINE preprocessor directive:
#DEFINE _SOCKADDR_LEN 1 |
This statement must appear before you include any of the following header files:
#include <in.h> #include <netdb.h> #include <inet.h> |
Certain parameters to the TCP/IP Services Sockets API functions require
typecasting to avoid Compaq C compilation warnings. Typecasting is
required because of parameter prototyping, which the Compaq C
header (filename.H) files have in order to comply with ANSI
standards. The Compaq Tru64 UNIX header files have different requirements
because their Sockets API functions are not parameter prototyped.
1.5 Using 64-Bit Addresses (Alpha Only)
For applications that run on OpenVMS Alpha systems, input and output (I/O) operations can be performed directly to and from the P2 or S2 addressable space by means of the 64-bit friendly $QIO and $QIOW system services.
To write data to a remote host, use the $QIO(IO$_WRITEVBLK) function with either the p1 (input buffer) or p5 (input buffer list) parameter. The address you specify for the parameter can be a 64-bit value.
To read data from a remote host, use the $QIO(IO$_READVBLK) function with either the p1 (output buffer) or p6 (output buffer list) parameter. The address you specify for the parameter can be a 64-bit value.
MACRO-32 does not provide 64-bit macros for system services. For more information about MACRO-32 programming support and for 64-bit addressing in general, see the OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features.
For more information about using the $QIO and $QIOW system services for 64-bit addressing, see Chapter 5 and Chapter 6.
You can use either the Sockets API or OpenVMS system services to write TCP/IP applications that run on your corporate network. These applications consist of a series of system calls that perform tasks, such as creating a socket, performing host and IP address lookups, accepting and closing connections, and setting socket options. These system calls are direct entry points that client and server processes use to obtain services from the TCP/IP kernel software. System calls look and behave exactly like other procedural calls in that they take arguments and return one or more results, including a status value. These arguments can contain values or pointers to objects in the application program.
This chapter describes the communication process followed by client and
server applications. This process reflects the sequence of system calls
within the client and server programs (see Tables 2-1 through
2-4). The chapter also includes Sockets API and OpenVMS system
services examples for each step in the communication process.
2.1 The Client/Server Communication Process
The most commonly used paradigm in constructing distributed applications is the client/server model. The requester, known as the client, sends a request to a server and waits for a response. The server is an application-level program that offers a service that can be reached over the network. Servers accept requests that arrive over the network, perform their service, and return the result to the client.
In addition to having a client and a server, the connection also has a
mode of communication. This variable can be either connection-oriented
or connectionless. When writing network applications, the developer
uses the mode of communication required by the application-level
service. Therefore, if the application-level service uses the
connection-oriented mode of communication, the developer uses the
virtual circuit or the Transmission Control Protocol (TCP) approach. If
the application-level service uses the connectionless mode of
communication, then the developer uses the datagram or the User
Datagram Protocol (UDP) approach.
2.1.1 Using the TCP Protocol
Figure 2-1 shows the communication process for a TCP client/server application.
Figure 2-1 Client/Server Communication Process Using TCP
In this figure:
For server applications that use the TCP protocol, Table 2-1 identifies the typical communication tasks, the applicable Sockets API function, and the equivalent OpenVMS system service.
Task | Sockets API Function | OpenVMS System Service Function |
---|---|---|
Create a socket | socket() |
$ASSIGN
$QIO(IO$_SETMODE) 1 |
Bind socket name | bind() | $QIO(IO$_SETMODE) 1 |
Define listener socket | listen() | $QIO(IO$_SETMODE) 1 |
Accept connection request | accept() | $QIO(IO$_ACCESS|IO$M_ACCEPT) |
Exchange data |
read()
recv() recvmsg() |
$QIO(IO$_READVBLK) |
write()
send() sendmsg() |
$QIO(IO$_WRITEVBLK) | |
Shut down the socket (optional) | shutdown() | $QIO(IO$_DEACCESS|IO$M_SHUTDOWN) |
Close and delete the socket | close() |
$QIO(IO$_DEACCESS)
$DASSGN |
For a client application using the TCP protocol, Table 2-2 shows the tasks in the communication process, the applicable Sockets API functions, and the equivalent OpenVMS system service.
Task | Sockets API Function | OpenVMS System Service Function |
---|---|---|
Create a socket | socket() |
$ASSIGN
$QIO(IO$_SETMODE) 1 |
Bind socket name | bind() | $QIO(IO$_SETMODE) 1 |
Connect to server | connect() | $QIO(IO$_ACCESS) |
Exchange data |
read()
recv() recvmsg() |
$QIO(IO$_READVBLK) |
write()
send() sendmsg() |
$QIO(IO$_WRITEVBLK) | |
Shut down the socket (optional) | shutdown() | $QIO(IO$_DEACCESS|IO$M_SHUTDOWN) |
Close and delete the socket | close() |
$QIO(IO$_DEACCESS)
$DASSGN |
Figure 2-2 shows the steps in the communication process for a client/server application using the UDP protocol.
Figure 2-2 UDP Socket Communication Process
In this figure:
For server applications using the UDP protocol, Table 2-3 identifies the tasks in the communication process, the Sockets API functions, and the equivalent OpenVMS system service function.
Task | Sockets API Function | OpenVMS System Service Function |
---|---|---|
Create a socket | socket() |
$ASSIGN
$QIO(IO$_SETMODE) 1 |
Bind socket name | bind() | $QIO(IO$_SETMODE) 1 |
Exchange data |
read()
recv() recvfrom() recvmsg() |
$QIO(IO$_READVBLK) |
write()
send() sendto() sendmsg() |
$QIO(IO$_WRITEVBLK) | |
Shut down the socket (optional) | shutdown() | $QIO(IO$_DEACCESS|IO$M_SHUTDOWN) |
Close and delete the socket | close() |
$QIO(IO$_DEACCESS)
$DASSGN |
For client applications using the UDP protocol, Table 2-4 describes the tasks in the communication process, the Sockets API function, and the equivalent OpenVMS system service.
Task | Sockets API Function | OpenVMS System Service Function |
---|---|---|
Create a socket | socket() |
$ASSIGN
$QIO(IO$_SETMODE) 1 |
Bind socket name (optional) | bind() | $QIO(IO$_SETMODE) 1 |
Specify a destination address for outgoing datagrams | connect() | $QIO(IO$_ACCESS) |
Exchange data |
read()
recv() recvfrom() recvmsg() |
$QIO(IO$_READVBLK) |
write()
send() sendto() sendmsg() |
$QIO(IO$_WRITEVBLK) | |
Shut down the socket (optional) | shutdown() | $QIO(IO$_DEACCESS|IO$M_SHUTDOWN) |
Close and delete the socket | close() |
$QIO(IO$_DEACCESS)
$DASSGN |
For network communication to take place between two processes, each process requires an end point to establish a communication link between the two processes. This end point, called a socket, sends messages to and receives messages from the socket associated with the process at the other end of the communication link.
Sockets are created by issuing a call to the socket() function (Sockets API) or by the $ASSIGN and $QIO(IO$_SETMODE) routines (system service) specifying an address family, a protocol family, and a socket type.
If the socket creation is successful, the operation returns a small nonnegative integer value called a socket descriptor, or sockfd. From this point on, the application program uses the socket descriptor to reference the newly created socket.
In the TCP/IP Services implementation, this socket is also referred to as a device socket. A device socket is the pairing of an OpenVMS network device and a BSD-style socket. A device socket can be created implicitly when using the Sockets API or explicitly when using OpenVMS system services.
To displaying information about a device socket, use the TCP/IP management command SHOW DEVICE_SOCKET.
Perform the following steps to create a socket:
The functions of the TCP/IP protocols are performed as I/O functions of the network device. When using the TCP/IP Services software, TCPIP$DEVICE: is the logical name for network devices.
When a channel is assigned to the TCPIP$DEVICE template network device, TCP/IP Services creates a new pseudodevice with a unique unit number and returns a channel number to use in subsequent operation requests with that device.
When the auxiliary server creates your application server process in
response to incoming network traffic for a service with the
LISTEN
flag, it creates a device socket for your application server process.
For your application to receive the device socket, assign a channel to
SYS$NET, which is the logical name of a network pseudodevice, and
perform an appropriate $QIO(IO$_SETMODE) operation. For examples of how
to do this, see Appendix E. For a discussion of the auxiliary server,
see the Compaq TCP/IP Services for OpenVMS Management manual.
2.2.1 Creating Sockets (Sockets API)
When using the Sockets API, create the socket with a call to the socket() function. Example 2-1 shows how to use the socket() function to create a TCP socket.
Example 2-1 Creating a Socket (Sockets API) |
---|
#include <socket.h> /* define BSD socket api */ #include <stdio.h> /* define standard i/o functions */ #include <stdlib.h> /* define standard library functions */ int main( void ) { int sockfd; /* * create a socket */ (1) if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror( "Failed to create socket" ); exit( EXIT_FAILURE ); } exit( EXIT_SUCCESS ); } |
When you use OpenVMS system services, you make two calls to create the socket:
When you make the $QIO or $QIOW call, use either the IO$_SETMODE or the IO$_SETCHAR I/O function. You generally create, bind, and set up sockets to listen with one $QIO call. The IO$_SETMODE and IO$_SETCHAR functions perform in an identical manner, where network software is concerned. However, you must have LOG_IO privilege to successfully use the IO$_SETMODE I/O function.
Example 2-2 shows how to use the $ASSIGN and $QIOW system services to create a TCP socket.
Example 2-2 Creating a Socket (System Services) |
---|
#include <descrip.h> /* define OpenVMS descriptors */ #include <efndef.h> /* define 'EFN$C_ENF' event flag */ #include <iodef.h> /* define i/o function codes */ #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 <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 sockchar { /* socket characteristics */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; int main( void ) { struct iosb iosb; /* i/o status block */ unsigned int status; /* system service return status */ unsigned short channel; /* network device i/o channel */ (1) struct sockchar sockchar; /* socket characteristics buffer */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of network pseudodevice */ /* * initialize socket characteristics */ (2) sockchar.prot = TCPIP$C_TCP; sockchar.type = TCPIP$C_STREAM; sockchar.af = TCPIP$C_AF_INET; /* * assign i/o channel to network device */ (3) 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 ); } /* * create a socket */ (4) status = sys$qiow( EFN$C_ENF, /* event flag */ channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &sockchar, /* p1 - socket characteristics */ 0, /* p2 */ 0, /* p3 */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to create socket\n" ); exit( status ); } exit( EXIT_SUCCESS ); } |
Previous | Next | Contents | Index |