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 |