| Previous | Contents | Index |
To bind a socket, specify a local interface address and local port number for the device socket.
If the application needs to receive incoming multicast or broadcast
datagrams destined for a specific UDP port, see Section 2.10 for
information about specifying the SO_REUSEPORT option when you bind the
socket.
2.4.1 Binding Sockets with OpenVMS System Services
Use the IO$_SETMODE or IO$_SETCHAR function of the $QIO system service to bind a socket.
The process must have a system user identification code (UIC), SYSPRV, BYPASS, or OPER privileges to bind port numbers 1 to 1023. |
Example 2-5 shows a TCP/IP server using the IO$_SETMODE function to bind sockets.
| Example 2-5 Binding Socket Using OpenVMS System Services |
|---|
/*
**
** Bind the socket to a local address.
**
*/
addrLength = sizeof( localAddr );
memset( &localAddr, 0, sizeof( localAddr ));
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = INADDR_ANY;
localAddr.sin_port = htons( SERVER_PORT );
/*
**
** Declare and populate a string descriptor, (struct dsc$descriptor_s),
** as defined in <descrip.h>.
**
*/
localAddrDSC.dsc$a_pointer = (char*)&localAddr;
localAddrDSC.dsc$w_length = (long)addrLength;
/*
**
** Attempt to Bind the device socket to the local host address.
** Use the function code of IO$_SETMODE, passing the local
** address information as a descriptor to P3.
**
** NOTE: The functionality of this call, to bind the socket, and the
** functionality of the sys$qiow call, to create the socket, could be
** combined into one call.
**
*/
sysSrvSts = sys$qiow( 0, /* efn.v | 0 */
IOChannel, /* chan.v */
IO$_SETMODE, /* func.v */
&iosb, /* iosb.r | 0 */
0, 0, /* astadr, astprm: UNUSED */
0, 0, /* p1, p2 UNUSED */
&localAddrDSC, /* p3.d Socket bind parameter */
0, 0, 0 /* p4, 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 );
}
|
Example 2-6 shows an example of a TCP/IP server using the bind() routine to bind a socket name.
| Example 2-6 Binding a Socket Using C Socket Programming |
|---|
#include <types.h>
#include <in.h>
#include <socket.h>
#include <unixio.h>
#include <string.h>
#define PORTNUM 1234
.
.
.
main() {
int r, s, i;
struct sockaddr_in lcladdr;
char *message = "Hello, world!\r\n";
lcladdr.sin_family = AF_INET;
lcladdr.sin_addr.s_addr = INADDR_ANY;
lcladdr.sin_port = htons(PORTNUM);
.
.
.
i = bind( s,
(struct sockaddr *)&lcladdr,(1)
sizeof(lcladdr));(2)
.
.
.
|
In this example, the bind() routine specifies the socket descriptor previously created with a call to the socket() routine, as follows:
Only server programs that use TCP need to set a socket to be a
listener. This allows the program to receive incoming connection
requests. (TCP, as a stream protocol, requires a connection. UDP, a
datagram protocl, does not.) To set a socket to listen for connection
requests, specify the number of incoming requests that can wait to be
queued for processing.
2.5.1 Listening to a Socket with OpenVMS System Services
Example 2-7 shows how to use the IO$_SETMODE function to set the socket to listen for requests.
| Example 2-7 Setting the Socket to Listen Using OpenVMS System Services |
|---|
#define SERVER_QLENGTH 3
/*
**
** Attempt to inform the network driver that it should enqueue multiple
** simultaneous incoming connection requests.
** Use the function code IO$_SETMODE, passing the desired queue
** length by value to P4. Should the queue of connection requests waiting to
** be accepted be at the specified limit, new connection requests are
** automatically rejected by the network driver.
**
*/
sysSrvSts = sys$qiow( 0, /* efn.v | 0 */
IOChannel, /* chan.v */
IO$_SETMODE, /* func.v */
&iosb, /* iosb.r | 0 */
0, 0, /* astadr, astprm: UNUSED */
0, 0, 0, /* p1, p2, p3 UNUSED */
SERVER_QLENGTH, /* p4.v Queue length */
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 );
}
|
Although you can issue separate $QIO calls for socket create, bind, and listen operations, you can also perform these operations with one $QIO call. Note that socket name means the same as socket address, and it represents the association of host address and port information. |
Example 2-8 shows a TCP/IP server using the bind() routine to set the socket to listen for requests.
| Example 2-8 Setting the Socket to Listen Using C Socket Programming |
|---|
#include <types.h>
#include <in.h>
#include <socket.h>
#include <unixio.h>
#include <string.h>
#define PORTNUM 1234
main() {
int r, s, i;
struct sockaddr_in lcladdr;
char *message = "Hello, world!\r\n";
memset( &lcladdr, 0, sizeof(lcladdr));
lcladdr.sin_family = AF_INET;
lcladdr.sin_addr.s_addr = INADDR_ANY;
lcladdr.sin_port = htons(PORTNUM);
.
.
.
i = listen(s,(1) 1);(2)
|
In this example of a listen() routine:
You can initiate a connection through a TCP client using either a stream socket or datagram. However, you must follow the guidelines listed below:
To initiate a connection to a remote host, issue the $QIO system service with the IO$_ACCESS function and the p3 argument. The p3 argument of the IO$_ACCESS function is the address of an item_list_2 descriptor that contains the remote socket name.
Example 2-9 shows an example of a TCP/IP client using the IO_$ACCESS function to initiate a connection.
The internet address received by the program identifies the remote host. To map the internet address to the host name, use a $QIO system service with the IO$_ACPCONTROL function (see Chapter 4).
| Example 2-9 Initiating a Connection Using OpenVMS System Services |
|---|
/*
**
** Get the remote server host name from the user and set up the remote
** address structure.
**
*/
memset( &remoteAddr, 0, sizeof( remoteAddr ));
remoteAddr.sin_family = AF_INET;
remoteAddr.sin_port = htons( SERVER_PORT_NUMBER );
/* Continue to prompt the user for a valid server host name. */
memset( IOBuff, 0, MaxBuff );
printf( "\n Enter the host name where the server is running : " );
scanf( "%s", IOBuff );
while( (hostentptr = gethostbyname( IOBuff )) == (struct hostent*)NULL )
{
printf( " Host %s could not be found.\n", IOBuff );
memset( IOBuff, 0, MaxBuff );
printf( "\n Enter the host name where the server is running : " );
scanf( "%s", IOBuff );
}
remoteInAddr.s_addr = *(int*)(hostentptr->h_addr);
addrStr = (char*)inet_ntoa( remoteInAddr );
printf( "\n connecting to: %s %s\n", hostentptr->h_name,
addrStr ));
remoteAddr.sin_addr = *((struct in_addr*)hostentptr->h_addr );
remoteAddrDSC.dsc$a_pointer = (char*)&remoteAddr;
remoteAddrDSC.dsc$w_length = sizeof( remoteAddr );
/*
**
** Attempt to connect the device socket to the local host address.
** Use the function code IO$_ACCESS, passing the remote
** address information as a descriptor to P3.
**
** NOTE: The functionality of this calln to connect the socket, and
** the functionality of the sys$qiow call, to create the socket,
** could be combined into one call.
**
*/
sysSrvSts = sys$qiow( 0, /* efn.v | 0 */
IOChannel, /* chan.v */
IO$_ACCESS, /* func.v */
&iosb, /* iosb.r | 0 */
0, 0, /* astadr, astprm: UNUSED */
0, 0, /* p1, p2 UNUSED */
&remoteAddrDSC, /* p3.d Socket connect parameter */
0, 0, 0 /* p4, 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 );
}
cleanup( IOChannel );
errorExit( sysSrvSts, iosb.cond_value );
}
|
To initiate a connection to a remote host, issue the connect() routine. Example 2-10 shows an example of a TCP/IP client using the connect() routine to initiate a connection to a remote server.
| Example 2-10 Initiating a Connection Using C Socket Programming |
|---|
.
.
.
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 */
.
.
.
/*
* Fill in the name & address structure for socket 2.
*/
sock2_name.sin_family = hostentstruct.h_addrtype;
sock2_name.sin_port = htons(atoi(argv[2]));
sock2_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr);
/*
* Connect socket 1 to sock2_name.
*/
retval = connect(sock_1, &sock2_name, sizeof (sock2_name));
if (retval)
{
perror("connect");
cleanup(shut, sock_1);
}
|
Your server program must be able to accept incoming connection requests
from client programs to successfully use TCP.
2.7.1 Accepting a Connection Using OpenVMS System Services
To accept a connection request, use the following procedure:
Specifying the IO$_ACCESS function is mandatory for TCP/IP. The IO$_ACCESS function uses the p4 argument only with the IO$M_ACCEPT modifier. |
Example 2-11 shows a TCP server using the IO$_ACCESS function with the IO$M_ACCEPT modifier to accept incoming connection requests.
| Example 2-11 Accepting an Incoming Connection Request Using OpenVMS System Services |
|---|
/*
**
** Assign a new channel, for the new connection, to the network device,
** "TCPIP$DEVICE:".
**
*/
sysSrvSts = sys$assign( &devDSC, /* devnam.d */
&IOChanClient, /* chan.r */
0, /* acmode.v | 0 */
0, /* mbxnam.d | 0 */
0 /* flags.v | 0 */ );
if(( sysSrvSts & 1 ) != 1 ) /* Validate the system service status. */
{
cleanup( IOChanClient );
cleanup( IOChannel );
errorExit( sysSrvSts, iosb.cond_value );
}
remoteAddrInfo.length = (unsigned int)addrLength;
remoteAddrInfo.address = (char*)&remoteAddr;
remoteAddrInfo.retLenPtr = (unsigned int*)&addrLength;
/*
**
** Attempt to complete the first connections on a queue of pending
** connections.
** Use the function codes of IO$_ACCESS ORed with IO$M_ACCEPT, passing the
** address of the remote address information to P3, and the address
** of the new channel to the client to P4.
**
** This queue must have previously been established with a QIO using
** function IO$_SETMODE and a queue length passed to P4.
**
*/
sysSrvSts = sys$qiow( 0, /* efn.v | 0 */
IOChannel, /* chan.v */
IO$_ACCESS |
IO$M_ACCEPT, /* func.v */
&iosb, /* iosb.r | 0 */
0, 0, /* astadr, astprm: UNUSED */
0, 0, /* p1, P2: UNUSED */
&remoteAddrInfo, /* p3.r Remote IP address */
&IOChanClient, /* p4.r connection Chan */
0, 0 /* p5, p6 UNUSED */ );
if((( sysSrvSts & 1 ) != 1 ) || /* Validate system service status. */
(( iosb.cond_value & 1 ) != 1)) /* Validate the IO status. */
{
cleanup( IOChanClient );
cleanup( IOChannel );
errorExit( sysSrvSts, iosb.cond_value );
}
printf( " SUCCEEDED in accepting a connections.\n" );
printf( " The client connection port number is %d\n",
htons( remoteAddr.sin_port ));
|
2.7.2 Accepting a Connection Using a C Socket Interface
Example 2-12 shows how to use the accept() routine.
| Example 2-12 Accepting a Connection Request Using C Socket Programming |
|---|
/*
* Accept connection from socket 2:
* accepted connection will be on socket 3
*/
namelength = sizeof (sock2_name);
sock_3 = accept (sock_2,(1)
& sock2_name,(2)
& namelength);(3)
if (sock_3 == -1)
{
perror ("accept");
cleanup( 2, sock_2, sock_3);
}
|
In this example of an accept() routine:
Obtaining device socket information is useful if your program has
management functions or if you have a complex program that uses
multiple connections you need to track.
2.8.1 Getting Device Socket Information with OpenVMS System Services
To obtain information about the parts of a device socket, use the following OpenVMS system services:
When using the $GETDVI system service, use the channel number (not TCPIP$DEVICE:) as an input parameter to $GETDVIW to obtain the correct unit number and characteristics of an internet pseudodevice. For information on $GETDVI and its parameters, refer to the OpenVMS Programming Concepts Manual and the OpenVMS System Services Reference Manual.
Example 2-13 shows an example of a TCP/IP client using the IO$_SENSEMODE function to get a local socket name.
| Example 2-13 Obtaining Device Socket Information by Using OpenVMS System Services |
|---|
/*
**
** This is a table listing some of the valid combinations of level to optname
**
** level:
** +-----------------------+---------------------------+----------------+
** | SOL_SOCKET | TCPIP$C_TCP | TCPIP$C_RAW_IP |
** +-----------------------+---------------------------+----------------+
** optname:
** +.......................+...........................+................+
** | TCPIP$C_RCVBUF | TCPIP$C_USELOOPBACK | TCPIP$C_IP_TTL |
** | TCPIP$C_SNDBUF | TCPIP$C_TCP_NODELAY | TCPIP$C_IP_TOS |
** | TCPIP$C_KEEPALIVE | TCPIP$C_TCP_PROBE_IDLE | |
** | TCPIP$C_REUSEADDR | TCPIP$C_TCP_DROP_IDLE | |
** | | TCPIP$C_FULL_DUPLEX_CLOSE | |
** +-----------------------+---------------------------+----------------+
**
*/
setSockOptType setSockOpt; /* Struct used to set socket options */
iLSockOptType setSockOptItemList;/* Item List of setSockOpt(s) */
int setSockOneOption = 1;
/*
**
** Set and validate option name and level.
**
*/
setSockOpt.length = sizeof( setSockOneOption );
setSockOpt.code = TCPIP$M_REUSEADDR;
setSockOpt.optBuffAddr = (char*)&setSockOneOption;
setSockOptItemList.length = sizeof( setSockOptType );
setSockOptItemList.optStructAddr = (char*) &setSockOpt;
setSockOptItemList.code = TCPIP$C_SOCKOPT;
/*
**
** Attempt to set options on the socket.
**
*/
sysSrvSts = sys$qiow( 0, /* efn.v | 0 */
IOChannel, /* chan.v */
IO$_SETMODE, /* func.v */
&iosb, /* iosb.r | 0 */
0, 0, /* astadr, astprm: UNUSED */
0, 0, 0, 0, /* p1, p2, p3, p4 UNUSED */
&setSockOptItemList, /* p5.r options item list */
0 /* 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 );
}
|
| Previous | Next | Contents | Index |