# include # include # include # include # include # include # include # include # include # define DATA_BUF_MAX 1000 # define DEBUG 0 int main ( int argc, char *argv[] ); void byte2int ( unsigned char *bvec, unsigned int *ival ); void int2byte ( unsigned int ival, unsigned char *bvec ); int socket_local ( SOCKET *local_socket ); int socket_remote ( char *remote_host_name, struct sockaddr_in *remote_addr ); int socket_send ( SOCKET local_socket, char data_buf[], int data_buf_size, struct sockaddr_in remote_addr ); void socket_terminate ( SOCKET local_socket ); /******************************************************************************/ int main ( int argc, char *argv[] ) /******************************************************************************/ /* Purpose: MAIN is the main program for PC_TO_IRIS. Discussion: This program runs on a Windows NT platform. The program: * starts up the Windows Socket API; * opens a socket on port 53000 that uses the UDP protocol; * sets up address information for a remote socket on host "zaphod.psc.edu" and port 53001; * sends messages to the remote socket; * closes the local socket and terminates the Windows Socket API. Licensing: This code is distributed under the GNU LGPL license. Modified: 12 November 1998 Author: John Burkardt Usage: pctoiris */ { char data_buf[DATA_BUF_MAX]; int data_buf_size; SOCKET local_socket; struct sockaddr_in remote_addr; char remote_host_name[81]; int result; /* Start the Windows Socket API, and set up the local socket. */ result = socket_local ( &local_socket ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " Could not open the local socket.\n" ); return 1; } /* Set up the address information for the remote socket. */ strcpy ( remote_host_name, "zaphod.psc.edu" ); result = socket_remote ( remote_host_name, &remote_addr ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " Could not set up the remote socket.\n" ); return 1; } /* Set up the data and send it. */ data_buf[0] = 'A'; data_buf[1] = ' '; data_buf[2] = 'M'; data_buf[3] = 'e'; data_buf[4] = 's'; data_buf[5] = 's'; data_buf[6] = 'a'; data_buf[7] = 'g'; data_buf[8] = 'e'; data_buf[9] = '!'; data_buf_size = 10; result = socket_send ( local_socket, data_buf, data_buf_size, remote_addr ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " socket_send error code = %d.\n", result ); } /* Send some more data. */ data_buf[0] = 'S'; data_buf[1] = 'e'; data_buf[2] = 'n'; data_buf[3] = 'd'; data_buf[4] = ' '; data_buf[5] = 'm'; data_buf[6] = 'o'; data_buf[7] = 'n'; data_buf[8] = 'e'; data_buf[9] = 'y'; data_buf[10] = '!'; data_buf_size = 11; result = socket_send ( local_socket, data_buf, data_buf_size, remote_addr ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " socket_send error code = %d.\n", result ); } /* Send some more data. */ data_buf[0] = 'S'; data_buf[1] = 'e'; data_buf[2] = 'q'; data_buf[3] = 'u'; data_buf[4] = 'e'; data_buf[5] = 'n'; data_buf[6] = 'c'; data_buf[7] = 'e'; data_buf[8] = ' '; data_buf[9] = 'E'; data_buf[10] = 'r'; data_buf[11] = 'r'; data_buf[12] = 'r'; data_buf[13] = 'o'; data_buf[14] = 'r'; data_buf[15] = '!'; data_buf_size = 16; result = socket_send ( local_socket, data_buf, data_buf_size, remote_addr ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " socket_send error code = %d.\n", result ); } /* Tell the remote socket we're shutting down. */ data_buf_size = 0; result = socket_send ( local_socket, data_buf, data_buf_size, remote_addr ); if ( result != 0 ) { printf ( "\n" ); printf ( "PC_TO_IRIS: ERROR!\n" ); printf ( " socket_send error code = %d.\n", result ); } /* Close the local socket and shut down the Windows Socket API. */ socket_terminate ( local_socket ); return 0; } /*****************************************************************************/ void byte2int ( unsigned char *bvec, unsigned int *ival ) /*****************************************************************************/ /* Purpose: BYTE2INT converts 4 bytes into an unsigned integer. Licensing: This code is distributed under the GNU LGPL license. Modified: 09 November 1998 Author: John Burkardt Parameters: Input, unsigned char *BVEC, is a pointer to a character string. The contents of BVEC through BVEC+3 are the bytes of IVAL, from high order to low. Output, unsigned int IVAL, the integer represented by the bytes. */ { int i; *ival = 0; for ( i = 0; i < 4; i++ ) { *ival = *ival << 8; *ival = *ival + *bvec; bvec = bvec + 1; } return; } /*****************************************************************************/ void int2byte ( unsigned int ival, unsigned char *bvec ) /******************************************************************************/ /* Purpose: INT2BYTE converts an unsigned integer into 4 bytes. Licensing: This code is distributed under the GNU LGPL license. Modified: 09 November 1998 Author: John Burkardt Parameters: Input, unsigned int IVAL, is the integer to be converted. Output, unsigned char *BVEC, is a pointer to a character string. The contents of BVEC through BVEC+3 will be the bytes of IVAL, from low order to high. */ { int i; for ( i = 0; i < 4; i++ ) { *bvec = ( ival >> (3-i)*8 ); bvec = bvec + 1; } } /*****************************************************************************/ int socket_local ( SOCKET *local_socket ) /******************************************************************************/ /* Purpose: SOCKET_LOCAL initializes the Windows Sockets API and creates a local socket. Licensing: This code is distributed under the GNU LGPL license. Modified: 12 November 1998 Author: John Burkardt Parameters: Output, SOCKET *local_socket, the descriptor of the local socket. */ { int domain; struct sockaddr_in local_addr; int local_addr_len; char local_host_name[81]; int local_host_name_len; unsigned short int local_port; int protocol; int result; int type; WSADATA wsadata; /* Initialize the WinSock API: WSVERS is the highest version of the WinSock specification that the application wishes to use. WSADATA is a pointer to a WSDATA structure. */ result = WSAStartup ( 0x0101, &wsadata ); if ( result != 0 ) { printf ( "\n" ); perror ( "SOCKET_LOCAL: WSAStartup" ); return 1; } printf ( "\n" ); printf ( "SOCKET_LOCAL:\n" ); printf ( " WSAStartup successful.\n" ); /* Report the local host name. */ local_host_name_len = 81; result = gethostname ( local_host_name, local_host_name_len ); printf ( " Local host is %s.\n", local_host_name ); /* Create a socket. DOMAIN is AF_INET, we will be using Internet addresses with this socket; TYPE is SOCK_DGRAM, the type of socket we will use; PROTOCOL is IPPROTO_UDP, the protocol to use with the socket. SD is the socket descriptor. */ domain = AF_INET; type = SOCK_DGRAM; protocol = IPPROTO_UDP; *local_socket = socket ( domain, type, protocol ); if ( *local_socket == 0 ) { printf ( "\n" ); perror ( "SOCKET_LOCAL: call to socket" ); return 1; } printf ( " Created local socket.\n" ); /* Bind the socket to a specific port number. The value for LOCAL_PORT is arbitrary, but the receiving program will need to know this value if it wants to send anything back. */ local_port = 53000; local_addr_len = sizeof ( local_addr ); memset ( &local_addr, 0, local_addr_len ); local_addr.sin_family = AF_INET; local_addr.sin_port = htons ( local_port ); local_addr.sin_addr.s_addr = htonl ( INADDR_ANY ); result = bind ( *local_socket, (LPSOCKADDR)&local_addr, local_addr_len ); if ( result == SOCKET_ERROR ) { printf ( "\n" ); perror ( "SOCKET_LOCAL: call to bind" ); return 1; } printf ( " Bound local socket to port number %d.\n", local_port ); return 0; } /*****************************************************************************/ int socket_remote ( char *remote_host_name, struct sockaddr_in *remote_addr ) /******************************************************************************/ /* Purpose: SOCKET_REMOTE returns the address of a remote host from its name. Licensing: This code is distributed under the GNU LGPL license. Modified: 12 November 1998 Author: John Burkardt Parameters: Input, char *remote_host_name, the name of the remote host with which we wish to communicate. Output, struct sockaddr_in *remote_addr, the pointer to a socket address structure. */ { int remote_addr_len; char *remote_addr_string; struct hostent *remote_host; unsigned short int remote_port; /* Based on the remote host name, get a pointer to the remote machine. */ remote_host = gethostbyname ( remote_host_name ); if ( !remote_host ) { printf ( "\n" ); printf ( "SOCKET_REMOTE: ERROR!\n" ); printf ( " Could not get host information.\n" ); return 1; } printf ( "\n" ); printf ( "SOCKET_REMOTE:\n" ); printf ( " Got host information.\n" ); /* Set up the address information for the remote machine. The REMOTE_PORT value here is arbitrary, but has to match the value defined in the receiving program. */ remote_port = 53001; remote_addr_len = sizeof ( *remote_addr ); memset ( remote_addr, 0, remote_addr_len ); remote_addr->sin_family = AF_INET; remote_addr->sin_port = htons ( remote_port ); remote_addr->sin_addr = * ( struct in_addr * ) ( remote_host->h_addr_list[0] ); remote_addr_string = inet_ntoa ( remote_addr->sin_addr ); printf ( " Remote Internet address is %s.\n", remote_addr_string ); return 0; } /*****************************************************************************/ int socket_send ( SOCKET local_socket, char data_buf[], int data_buf_size, struct sockaddr_in remote_addr ) /******************************************************************************/ /* Purpose: SOCKET_SEND sends data via the local socket to the remote port. Licensing: This code is distributed under the GNU LGPL license. Modified: 12 November 1998 Author: John Burkardt Parameters: Input, SOCKET local_socket, the descriptor of the local socket. Input, char data_buf[], bytes to be transmitted to the remote address. Input, int data_buf_size, the number of bytes to be transmitted. A value less than 1 is a special flag indicating that the remote socket should be told to shut down. Input, struct sockaddr_in remote_addr, the remote address. Output, int socket_send, 0 for success, header and data were sent; 1 if the header was only partially transmitted; 2 if the header was not sent; 3 if the message was only partially transmitted; 4 if the message was not sent. */ { unsigned char header_buf[8]; static int header_buf_size = 8; int i; int remote_addr_len; int result; static int send_flags = 0; static unsigned int sequence = 0; remote_addr_len = sizeof ( remote_addr ); /* First, send a message with the sequence number and number of bytes. */ sequence = sequence + 1; /* Just for fun, skip sequence number 3. */ if ( sequence == 3 ) { sequence = 4; } /* Convert the header to bytes. */ int2byte ( sequence, header_buf ); int2byte ( data_buf_size, header_buf+4 ); if ( DEBUG ) { printf ( "\n" ); printf ( "SOCKET_SEND: DEBUG:\n" ); printf ( " Sequence is %d.\n", sequence ); printf ( " Data_buf_size is %d.\n", data_buf_size ); for ( i = 0; i < 8; i++ ) { printf ( "%d %d\n", i, header_buf[i] ); } } result = sendto ( local_socket, header_buf, header_buf_size, send_flags, (const struct sockaddr *) &remote_addr, remote_addr_len ); if ( result < 0 ) { printf ( "\n" ); perror ( "SOCKET_SEND: header sendto" ); return 2; } else if ( result != header_buf_size ) { printf ( "\n" ); printf ( "SOCKET_SEND: ERROR!\n" ); printf ( " Not all of the header was sent.\n" ); return 1; } else { printf ( "\n" ); printf ( "SOCKET_SEND:\n" ); printf ( " Header sent to remote socket.\n" ); } /* If DATA_BUF_SIZE <= 0, the user is telling the remote process goodbye. */ if ( data_buf_size <= 0 ) { return 0; } /* Second, send the user's data. */ result = sendto ( local_socket, data_buf, data_buf_size, send_flags, (const struct sockaddr *) &remote_addr, remote_addr_len ); if ( result < 0 ) { printf ( "\n" ); perror ( "SOCKET_SEND: data sendto" ); return 4; } else if ( result != data_buf_size ) { printf ( "\n" ); printf ( "SOCKET_SEND: ERROR!\n" ); printf ( " Not all the data was sent.\n" ); return 3; } else { printf ( " Data sent to remote socket.\n" ); } return 0; } /*****************************************************************************/ void socket_terminate ( SOCKET local_socket ) /******************************************************************************/ /* Purpose: SOCKET_TERMINATE closes the local socket and terminates the Socket API. Licensing: This code is distributed under the GNU LGPL license. Modified: 12 November 1998 Author: John Burkardt Parameters: Input, SOCKET local_socket, the descriptor of the local socket that is to be closed. */ { closesocket ( local_socket ); printf ( "\n" ); printf ( "SOCKET_TERMINATE:\n" ); printf ( " Closing the local socket.\n" ); WSACleanup ( ); printf ( " Shutting down the Windows Socket API.\n" ); return; }