Previous | Contents | Index |
To initiate a connection to a TCP server, use 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 points to the remote socket name.
Example 2-8 shows a TCP client using the IO_$ACCESS function to initiate a connection.
Example 2-8 Initiating a Connection (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 */ #define BUFSZ 1024 /* user input buffer size */ #define PORTNUM 12345 /* server port number */ 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 itemlst_2 { /* item-list 2 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ }; struct sockchar { /* socket characteristics */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; void get_servaddr( void *addrptr ) { char buf[BUFSIZ]; struct in_addr val; struct hostent *host; while ( TRUE ) { printf( "Enter remote host: " ); if ( fgets(buf, sizeof(buf), stdin) == NULL ) { printf( "Failed to read user input\n" ); exit( EXIT_FAILURE ); } buf[strlen(buf)-1] = 0; val.s_addr = inet_addr( buf ); if ( val.s_addr != INADDR_NONE ) { memcpy( addrptr, &val, sizeof(struct in_addr) ); break; } if ( (host = gethostbyname(buf)) ) { memcpy( addrptr, host->h_addr, sizeof(struct in_addr) ); break; } } } 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 */ struct sockchar sockchar; /* socket characteristics buffer */ struct sockaddr_in addr; /* socket address structure */ struct itemlst_2 addr_itemlst; /* socket address item-list */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of network pseudodevice */ /* * initialize socket characteristics */ sockchar.prot = TCPIP$C_TCP; sockchar.type = TCPIP$C_STREAM; sockchar.af = TCPIP$C_AF_INET; /* * initialize socket address item-list descriptor */ addr_itemlst.length = sizeof( addr ); addr_itemlst.type = TCPIP$C_SOCK_NAME; addr_itemlst.address = &addr; /* * initialize socket address structure */ memset( &addr, 0, sizeof(addr) ); addr.sin_family = TCPIP$C_AF_INET; addr.sin_port = htons( PORTNUM ); get_servaddr( &addr.sin_addr ); /* * 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 ); } /* * create a socket */ 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 ); } /* * connect to specified host and port number */ printf( "Initiated connection to host: %s, port: %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) ); status = sys$qiow( EFN$C_ENF, /* event flag */ channel, /* i/o channel */ IO$_ACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &addr_itemlst, /* p3 - remote socket name */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to connect to server\n" ); exit( status ); } exit( EXIT_SUCCESS ); } |
A TCP server program must be able to accept incoming connection requests from client programs. The accept() function:
Example 2-9 shows how to use the accept() function.
Example 2-9 Accepting a Connection (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 <socket.h> /* define BSD socket api */ #include <stdio.h> /* define standard i/o functions */ #include <stdlib.h> /* define standard library functions */ #include <string.h> /* define string handling functions */ #define SERV_BACKLOG 1 /* server backlog */ #define SERV_PORTNUM 12345 /* server port number */ int main( void ) { int conn_sockfd; /* connection socket descriptor */ int listen_sockfd; /* listen socket descriptor */ unsigned int cli_addrlen; /* returned length of client socket */ /* address structure */ struct sockaddr_in cli_addr; /* client socket address structure */ struct sockaddr_in serv_addr; /* server socket address structure */ /* * initialize client's socket address structure */ memset( &cli_addr, 0, sizeof(cli_addr) ); /* * initialize server's socket address structure */ memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons( SERV_PORTNUM ); serv_addr.sin_addr.s_addr = INADDR_ANY; /* * create a listen socket */ if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror( "Failed to create socket" ); exit( EXIT_FAILURE ); } /* * bind server's ip address and port number to listen socket */ if ( bind(listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 ) { perror( "Failed to bind socket" ); exit( EXIT_FAILURE ); } /* * set socket as a listen socket */ if ( listen(listen_sockfd, SERV_BACKLOG) < 0 ) { perror( "Failed to set socket passive" ); exit( EXIT_FAILURE ); } /* * accept connection from a client */ printf( "Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port) ); cli_addrlen = sizeof(cli_addr); conn_sockfd = accept( listen_sockfd, (1) (struct sockaddr *) &cli_addr, (2) &cli_addrlen (3) ); if ( conn_sockfd < 0 ) { perror( "Failed to accept client connection" ); exit( EXIT_FAILURE ); } printf( "Accepted connection from host: %s, port: %d\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) ); exit( EXIT_SUCCESS ); } |
In this example of an accept() function:
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-10 shows a TCP server using the IO$_ACCESS function with the IO$M_ACCEPT function modifier to accept incoming connection requests.
Example 2-10 Accepting a Connection (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 */ #define SERV_BACKLOG 1 /* server backlog */ #define SERV_PORTNUM 12345 /* server port number */ 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 itemlst_2 { /* item-list 2 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ }; struct itemlst_3 { /* item-list 3 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ unsigned int *retlen; /* address of returned length */ }; 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 conn_channel; /* connect inet device i/o channel */ unsigned short listen_channel; /* listen inet device i/o channel */ struct sockchar listen_sockchar; /* listen socket characteristics */ unsigned int cli_addrlen; /* returned length of client socket */ /* address structure */ struct sockaddr_in cli_addr; /* client socket address structure */ struct itemlst_3 cli_itemlst; /* client socket address item-list */ struct sockaddr_in serv_addr; /* server socket address structure */ struct itemlst_2 serv_itemlst; /* server socket address item-list */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of network pseudodevice */ /* * initialize socket characteristics */ listen_sockchar.prot = TCPIP$C_TCP; listen_sockchar.type = TCPIP$C_STREAM; listen_sockchar.af = TCPIP$C_AF_INET; /* * initialize client's item-list descriptor */ memset( &cli_itemlst, 0, sizeof(cli_itemlst) ); cli_itemlst.length = sizeof( cli_addr ); cli_itemlst.address = &cli_addr; cli_itemlst.retlen = &cli_addrlen; /* * initialize client's socket address structure */ memset( &cli_addr, 0, sizeof(cli_addr) ); /* * initialize server's item-list descriptor */ serv_itemlst.length = sizeof( serv_addr ); serv_itemlst.type = TCPIP$C_SOCK_NAME; serv_itemlst.address = &serv_addr; /* * initialize server's socket address structure */ memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = TCPIP$C_AF_INET; serv_addr.sin_port = htons( SERV_PORTNUM ); serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; /* * assign i/o channels to network device */ status = sys$assign( &inet_device, /* device name */ &listen_channel, /* i/o channel */ 0, /* access mode */ 0 /* not used */ ); if ( status & STS$M_SUCCESS ) status = sys$assign( &inet_device, /* device name */ &conn_channel, /* i/o channel */ 0, /* access mode */ 0 /* not used */ ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to assign i/o channel(s)\n" ); exit( status ); } /* * create a listen socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &listen_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 ); } /* * bind server's ip address and port number to listen socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &serv_itemlst, /* p3 - local socket name */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to bind socket\n" ); exit( status ); } /* * set socket as a listen socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ 0, /* p3 */ SERV_BACKLOG, /* p4 - connection backlog */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to set socket passive\n" ); exit( status ); } /* * accept connection from a client */ printf( "Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port) ); status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_ACCESS|IO$M_ACCEPT, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &cli_itemlst, /* p3 - remote socket name */ &conn_channel, /* p4 - i/o channel for new */ /* connection */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to accept client connection\n" ); exit( status ); } printf( "Accepted connection from host: %s, port: %d\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) ); exit( EXIT_SUCCESS ); } |
Previous | Next | Contents | Index |