Advertisement
Guest User

C++ UDP Client

a guest
Apr 24th, 2012
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.40 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <netdb.h> 
  10.  
  11. #define RSP         0x00 // Response
  12. #define RQS         0x01 // Request
  13. #define C_EOF       0x02 // End of file (response)
  14. #define FILE_N_FND  0x04 // File not Found (response)
  15.  
  16. #define MAX_MESSAGE 1400
  17.  
  18. /// STRUCT ====================================================================
  19. /* Protocol for UPACK
  20. Flags (bit 0 is LSB)
  21.     bit 0 : 1 = request, 0 = response
  22.     bit 1 : 1 = eof encountered (response)
  23.     bit 2 : 1 = file not found (response)
  24.     bit 3 : 1 = invalid request (response)
  25.     bits 4..7 : not used, should be 0
  26. Length: 16-bit unsigned integer length of requested file block (request), length of data field returned (response).
  27. Offset: 32-bit unsigned integer offset within a requested file to start supplying data (request and response).
  28. Filename: 32 byte ASCII character array with requested filename. Filename will be left-justified, and null-terminated.
  29. Data: not included in request, contains requested file data in response.
  30. */
  31. typedef struct UPACK {
  32.     uint8_t  flags;
  33.     uint16_t length;
  34.     uint32_t offset;
  35.     unsigned char* filename[MAX_MESSAGE];
  36.     unsigned char data[MAX_MESSAGE];
  37. } UPACK;
  38. /// STRUCT ====================================================================
  39.  
  40.     /**
  41.     Crash handler
  42.     */
  43. void crash(char *s) {
  44.     perror(s);
  45.     exit(1);
  46. }
  47.  
  48.     /**
  49.     Minor Crash handler
  50.     */
  51. int mcrash(char *s) {
  52.     perror(s);
  53.     return -1;
  54. }
  55.  
  56.     // create socket
  57.     // IP protocol family (PF_INET)
  58.     // UDP (SOCK_DGRAM)
  59. int create_socket() {
  60.     int sock = 0;
  61.     if ((sock = socket(PF_INET, SOCK_DGRAM, 0 )) < 0) crash("Alert Comrade: Socket not created");
  62.     else    
  63.         return sock;
  64. }
  65.  
  66.     // UDP  Using UDP we don't need to call bind unless we
  67.     // want to specify a "source" port number.  We really
  68.     // do not care - server will reply to whatever port we
  69.     // are given
  70.  
  71.     // Make a sockaddr of the server
  72.     // address family is IP  (AF_INET)
  73.     // server IP address is found by calling gethostbyname with the
  74.     // name of the server (entered on the command line)
  75.     // note, if an IP address is provided, that is OK too
  76.  
  77.     //load data into the socket address struct
  78. void load_socket_address(sockaddr_in * SVR, char* IP, char* PORT) {
  79.     SVR -> sin_family        = AF_INET;
  80.  
  81.     unsigned short tport = 0;
  82.  
  83.     if(sscanf(PORT, "%hu", &tport) != 1) crash("Alert Comrade: Invalid Port");
  84.  
  85.     SVR -> sin_port          = htons(tport);
  86.  
  87.     int check = 0;
  88.    
  89.     check = inet_pton(AF_INET, IP, &SVR -> sin_addr);
  90.  
  91.     if(check == 1)
  92.         printf("great success\n");
  93.     else if(check == 0)
  94.         printf("no string here\n");
  95.     else if(check == -1)
  96.         printf("bug\n");
  97.  
  98.     //netdb.h
  99.     //hostent *host;
  100.     //if((host = gethostbyname(PORT)) == 0) crash("Alert Comrade: Invalid/Unknown Host");
  101.  
  102.     //memcpy(&SVR -> sin_addr.s_addr, host->h_addr, host->h_length);
  103.  
  104.     SVR -> sin_addr.s_addr = inet_addr(IP);
  105.  
  106.     printf("Imperial Soviet Comrade: SVN -> sin_family: %d\n", SVR -> sin_family);
  107.     printf("Imperial Soviet Comrade: SVN -> sin_port: %d\n", SVR -> sin_port);
  108.     printf("Imperial Soviet Comrade: SVN -> sin_addr: %d\n", SVR -> sin_addr);
  109.     //printf("Imperial Soviet Comrade: host -> h_addr: %d\n", host->h_addr);
  110.     //printf("Imperial Soviet Comrade: host -> h_length: %d\n", host->h_length);
  111.  
  112. }
  113.  
  114.     //Load the data into the UDP Packet
  115. void load_UDP_packet(UPACK* UPC, uint8_t FLG, uint16_t LEN, uint32_t OFF) {
  116.     UPC -> flags    = FLG;
  117.     UPC -> length   = LEN;
  118.     UPC -> offset   = OFF;
  119.  
  120.     //alert the user to the need for data
  121.     printf("Attention Comrade: Enter Message: ");
  122.     char buffer[MAX_MESSAGE];
  123.  
  124.     //get the next string entered into the command prompt
  125.     fgets(buffer, MAX_MESSAGE, stdin);
  126.  
  127.     //copy the data from the command prompt into the packet
  128.     memcpy(UPC -> filename, buffer, strlen(buffer));
  129. }
  130.  
  131.     //send the packet out
  132. void send_packet (int SOCKET, UPACK* UPC, sockaddr_in* TARGET) {
  133.     unsigned char* PACKET_DATA = (unsigned char *) UPC;
  134.     printf("\n\nImperial Soviet Comrade: Data in packet dump ::::::::::::::::::::::::::::::::::::::::: start\n");
  135.     printf("Imperial Soviet Comrade: the size of the UPC is %lu\n", (sizeof(*UPC)/8));
  136.     printf("Imperial Soviet Comrade: Socket: %d\n", SOCKET);
  137.     printf("Imperial Soviet Comrade: UPC -> flags: %d\n", UPC -> flags);
  138.     printf("Imperial Soviet Comrade: UPC -> offset: %d\n", UPC -> offset);
  139.     printf("Imperial Soviet Comrade: UPC -> length: %d\n", UPC -> length);
  140.     printf("Imperial Soviet Comrade: UPC -> filename: %s", UPC -> filename);
  141.     printf("Imperial Soviet Comrade: UPC -> data: ");
  142.     for(int i = 0; i < sizeof(UPC -> data); i++) {
  143.         if (((i%80) == 0) && (i != 0)) printf("\nImperial Soviet Comrade: UPC -> data: ");
  144.         printf("%d", ((UPACK *) UPC) -> data[i]);
  145.     }
  146.     printf("\n");
  147.  
  148.     printf("Imperial Soviet Comrade: sizeof(UPC): %d\n", sizeof(UPC));
  149.     printf("Imperial Soviet Comrade: sockaddr.sin_family: %d\n", TARGET -> sin_family);
  150.     printf("Imperial Soviet Comrade: sockaddr.sin_port: %d\n", TARGET -> sin_port);
  151.     printf("Imperial Soviet Comrade: sockaddr.sin_addr.s_addr: %d\n", TARGET -> sin_addr.s_addr);
  152.     printf("Imperial Soviet Comrade: sizeof(sockaddr): %d\n", sizeof(TARGET));
  153.     printf("Imperial Soviet Comrade: Data in packet dump ::::::::::::::::::::::::::::::::::::::::::: end\n\n\n");
  154.     int size_sent = sendto(SOCKET, UPC, sizeof(UPC)+2*MAX_MESSAGE, 0, (struct sockaddr*) &TARGET, sizeof(TARGET)+2*MAX_MESSAGE);
  155.  
  156.     printf("Imperial Soviet Comrade: size_sent: %d\n", size_sent);
  157.  
  158.     if(size_sent < 0) crash("Alert Comrade: Data not sent");
  159. }
  160.  
  161.     // Handle returning packets
  162. int process_incoming(int SOCKET, UPACK* UPC, FILE* TARGET_FILE) {
  163.     // Create a Buffer    
  164.     char buffer[MAX_MESSAGE];
  165.    
  166.     // clear the space
  167.     memset(buffer, 0, MAX_MESSAGE);
  168.  
  169.     // setup the timeout - 5 seconds
  170.     struct timeval time_out = {5,0};
  171.    
  172.     // create a file descriptor set
  173.     fd_set incoming_message_socket;
  174.    
  175.     // zero out the dataset at incoming_message_socket
  176.     FD_ZERO(&incoming_message_socket);
  177.  
  178.     // Sets the SOCKET as the listened to incoming data
  179.     FD_SET(SOCKET, &incoming_message_socket);
  180.  
  181.     //originally sock+1
  182.     if (select(SOCKET, &incoming_message_socket, 0, 0, &time_out) < 0)
  183.         return mcrash("Alert Comrade: Error on select\n");
  184.    
  185.     // something was returned!
  186.     if (FD_ISSET(SOCKET, &incoming_message_socket))
  187.     {
  188.         // Get data back from parts unknown - hopefully the targetted server
  189.         int ECHO = recvfrom(SOCKET, buffer, MAX_MESSAGE, 0, NULL, NULL);
  190.        
  191.         // something went wrong with receiving
  192.         if (ECHO < 0) crash("Alert Comrade: Error receiving\n");
  193.        
  194.         // file not found
  195.         else if(UPC -> flags == C_EOF)
  196.             return mcrash("Alert Comrade: File Not Found\n");
  197.  
  198.         // Something went right! About damn time... It's time to grab this data and toss it into a file!
  199.         else {
  200.             //filename is as what was requested, pointer for writing appends to the end of the file
  201.             for(int i = 0; i < MAX_MESSAGE; i++)            
  202.                 TARGET_FILE = fopen((const char*) UPC -> filename, (const char*) 'a');
  203.  
  204.             //print data to file
  205.             fprintf(TARGET_FILE, (const char *) UPC -> data);
  206.            
  207.             //close the output to the file
  208.             fclose(TARGET_FILE);
  209.  
  210.             //if the end of file was found            
  211.             if(UPC -> flags == C_EOF) return C_EOF;
  212.            
  213.             //if there is more data to be sent over
  214.             else if(UPC -> flags == RSP) return RSP;
  215.         }
  216.     }
  217.     else return mcrash("Alert Comrade: Timeout - Server is not listening, or packet was dropped.\n");
  218.    
  219.     return 3;
  220. }
  221.  
  222. int main(int argc, char **argv) {
  223.  
  224. using namespace std;
  225.  
  226.     struct sockaddr_in target;
  227.  
  228.     //ensure a correct number of arguments
  229.     if(argc != 3) {
  230.         printf("Alert Comrade: invalid number of arguments.\n");
  231.         printf("Command Required: sudo ./a.out 'IP Address' 'Port Number'\n");
  232.         exit(0);
  233.     }
  234.    
  235.     //create the socket
  236.     int socket = create_socket();    
  237.  
  238.     //load the socket address into target
  239.     load_socket_address(&target, argv[1], argv[2]);
  240.    
  241.     //create space for the packet
  242.     UPACK *UPACKET = (UPACK *) malloc(sizeof(UPACK));
  243.  
  244.     //response
  245.     int response_from_server = 0;
  246.  
  247.     //File to use in order to process requests
  248.     FILE* data_dump;
  249.  
  250.     //offset counter
  251.     int offset = 0;    
  252.    
  253.     //retry counter
  254.     int retry = 0;
  255.  
  256.     //Allow the user to send and recieve data
  257.     while(1) {
  258.         //reset offset
  259.         offset = 0;
  260.  
  261.         // if this is not a resend
  262.         if(response_from_server != 3)
  263.             //fill the packet with data
  264.             load_UDP_packet(UPACKET, RQS, sizeof(UPACKET), offset);
  265.         // if this is trying to resend
  266.         else {
  267.             //add a count to retry
  268.             retry++;
  269.             printf("Imperial Soviet Comrade: Resend Attempt %d\n", retry);
  270.         }
  271.         //shoot that packet down the wire
  272.         send_packet(socket, UPACKET, &target);
  273.  
  274.         //recieve the packet
  275.         response_from_server = process_incoming(socket, UPACKET, data_dump);
  276.  
  277.         //There's more data to be sent
  278.         if(response_from_server == RSP) {
  279.             retry = 0;
  280.  
  281.             while(response_from_server == RSP) {
  282.                  //fill the packet with data, increment the offset
  283.                 load_UDP_packet(UPACKET, RQS, sizeof(UPACKET), offset++);
  284.  
  285.                 //shoot that packet down the wire
  286.                 send_packet(socket, UPACKET, &target);
  287.  
  288.                 //recieve the packet
  289.                 response_from_server = process_incoming(socket, UPACKET, data_dump);
  290.             }
  291.         }
  292.         else if (response_from_server == C_EOF) {
  293.             printf("Imperial Soviet Comrade: File Fully Recieved\n");
  294.         }
  295.         else if (retry >= 3) {
  296.             printf("Imperial Soviet Comrade: Transmission Failed 3 Times. Closing Connection to Server.\n");
  297.             retry = 0;
  298.         }
  299.         //  do nothing - EOF lets you know by coming back aroumd
  300.     }
  301.     return(0);
  302. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement