/* tcpip-client-sock.c This program is the client portion. It does the following 1. Creates socket. 2. Binds socket. 3. Starts looping. 4. Get's user input. 5. sends connection request. 6. Writes data to socket. 7. Waits for acknowledgment. 8. Goes back to loop beginning 9. Deletes socket. 10. exits. */ #include /* define OpenVMS descriptors */ #include /* define 'EFN$C_ENF' event flag */ #include /* define internet related constants, */ /* functions, and structures */ #include /* define network address info */ #include /* define i/o function codes */ #include /* define library routines */ #include /* define network database library info */ #include /* define rms functions, structures */ #include /* define system service status codes */ #include /* define system service calls */ #include /* define standard i/o functions */ #include /* define standard library functions */ #include /* define string handling functions */ #include /* define condition value fields */ #include /* define tcpip/ip network constants */ /* structures, and functions */ /* * NAMED CONSTANTS */ #define BUFSZ 1024 /* user input buffer size */ #define SERV_PORTNUM 12345 /* server port number */ #define max_msg_len 256 /* maximum message length */ #define $ARRAY_DESCRIPTOR(name,size,array_name) \ char array_name[ size ]; \ struct dsc$descriptor_s name = \ { size, DSC$K_DTYPE_T, DSC$K_CLASS_S, array_name } /* * Structure definitions */ 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 itemlist_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 buffer */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; /* * FORWARD REFERENCES */ int main(void); /* client main */ void get_serv_addr( void * ); /* get server host address */ int main(void) { struct iosb iosb; /* i/o status block */ struct sockchar conn_sockchar; /* connect socket char buffer */ struct itemlist_2 serv_itemlst; /* server item-list 2 descriptor */ struct sockaddr_in serv_addr; /* server socket address structure */ unsigned int status; /* system service return status */ unsigned short conn_channel; /* connection channel */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:"); /* name of internet pseudodevice */ $DESCRIPTOR(prompt_string_desc,"DATA TO SEND TO SERVER ( to terminate) >>> "); $ARRAY_DESCRIPTOR(write_buffer_desc,max_msg_len,write_buffer); int done = FALSE; /* Loop Flag */ char inbuffer[BUFSZ]; unsigned int inbuflen=BUFSZ; /* * init connection socket characteristics buffer */ conn_sockchar.prot = TCPIP$C_TCP; conn_sockchar.type = TCPIP$C_STREAM; conn_sockchar.af = TCPIP$C_AF_INET; /* * init server's item-list descriptor */ memset( &serv_itemlst, 0, sizeof(serv_itemlst) ); serv_itemlst.length = sizeof( serv_addr ); serv_itemlst.address = &serv_addr; /* * init 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 ); get_serv_addr(&serv_addr.sin_addr); /* * assign device socket */ 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 to TCPIP device\n" ); exit( status ); } /* * Loop forever, getting user input, and sending it across the TCPIP * connection. */ while ( !(done) ) { write_buffer_desc.dsc$w_length = max_msg_len; status = lib$get_input( &write_buffer_desc, &prompt_string_desc, &write_buffer_desc.dsc$w_length); /* * If at end of file (user typed ) * send exit signal */ if (status == RMS$_EOF) { strcpy(write_buffer_desc.dsc$a_pointer,"exit"); write_buffer_desc.dsc$w_length = 4; done = TRUE; } /* * create connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &conn_sockchar, /* p1 - socket char buffer */ 0,0,0,0,0); /* p2 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to create socket\n" ); exit( status ); } /* * Initiate connection to server */ printf( "Initiated connection to host: %s, port: %d\n", inet_ntoa(serv_addr.sin_addr),ntohs(serv_addr.sin_port)); status = sys$qiow( EFN$C_ENF, /* event flag */ conn_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 */ &serv_itemlst, /* p3 - remote socket name */ 0,0,0); /* p4 - p6 */ if (status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to connect to server\n"); exit( status ); } /* * Connection established with server; * now attempt to send user's input. */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_WRITEVBLK, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ write_buffer_desc.dsc$a_pointer, /* p1 */ write_buffer_desc.dsc$w_length, /* p2 */ 0,0,0,0); /* p3 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to write to connection.\n"); exit(status); } /* * Message sent. Wait for acknowledgement from server */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_READVBLK, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &inbuffer, /* input buffer address */ inbuflen, /* input buffer length */ 0,0,0,0); /* p3 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to read data from server connection\n"); exit(status); } printf( "Data received: %s\n", inbuffer); /* * shutdown connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS|IO$M_SHUTDOWN, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0,0, /* p1 - p3 */ TCPIP$C_DSC_ALL, /* p4 - discard all packets */ 0,0); /* p5 - p5 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to shutdown server connection\n"); exit(status); } printf( "Connection to server shutdown.\n"); /* * close connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0,0,0,0,0); /* p1 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to close socket.\n"); exit(status); } printf( "Socket Closed.\n"); } /* * deassign device socket */ status = sys$dassgn( conn_channel ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to close socket.\n"); exit(status); } return SS$_NORMAL; } void get_serv_addr( void *addrptr ) { char buf[BUFSZ]; 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; } } }