Thread: Client and Server code that sends contents of a file.

  1. #1
    Registered User
    Join Date
    Oct 2011
    Location
    New Mexico
    Posts
    10

    Client and Server code that sends contents of a file.

    I am working on Experiment 5.3 from the book Hands-On Networking with Internet Technologies. We have to modify client and server files. We want these files to form a connection, then the client will input a file that is wants from the server. This file is sent to the server, and the server sends what is stored within that file to the client. The client stores it in a file of the same name and prints the contents of the file to the terminal. The two files below are run with other files that were provided from the book, but only the files below need to be modified. Any help is appreciated or useful links to point me in the right direction. I am stuck on the send function line towards the end of fileserver.c.
    Thanks!!!

    Below is my client (fileclient.c) code
    Code:
    #include <stdio.h>
    #include <stdlib.h>            //Added
    #include "cnaiapi.h"            //Added
    
    
    #define MAX_CNAME               10                    //Added
    
    
    int recvln(connection, char *, int);        //Added
    int readln(char *, int);            //Added
    
    int                                          //Added
    main(int argc, char *argv[])             //Added
    {
        FILE *fp;
        char ch;
        computer    comp;               //Added
        connection    conn;               //Added
        char            cname[MAX_CNAME];   //Added
        int        len;            //Added
    
        if (argc != 3) {                                                         //Added
            (void) fprintf(stderr, "usage: %s <compname> <appnum>\n",        //Added
                       argv[0]);                     //Added
            exit(1);                             //Added
        }                                      //Added
    
        /* convert the compname to binary form comp */                           //Added
    
        comp = cname_to_comp(argv[1]);                         //Added
        if (comp == -1)                                 //Added
            exit(1);                             //Added
    
        /* Input File Name to use */                        //Added     
        printf ("Enter The name of the file to retrieve. \n");                //Added
        len = readln( cname, MAX_CNAME);                    //Added
    
        /* make a connection to the chatserver */                   //Added
    
        conn = make_contact(comp, (appnum) atoi(argv[2]));            //Added
        if (conn < 0)                                 //Added
            exit(1);                                //Added
    
        (void) printf("Chat Connection Established.\n");                        //Added
    
    
    
    
        // OPEN THE FILE => LOAD THE CONTENT OF THE FILE IN MEMORY
        fp = fopen("log.txt", "r");        //Here we have to open the file that was enter to retrieve above and len instead of log.txt does not work 
        if (fp == NULL){
            printf("We were not able to open the file\n");
            exit(0);
        }
    
        // PRINT THE FILE INTO THE SCREEN
        /*while (1){
            ch = fgetc(fp);
            if (ch == EOF){
                // HERE WE FOUND THE END OF THE FILE
                break;
            }
            printf("%c",ch);
        }*/
    
        fclose(fp);
        return 1;
    }
    Below is the server (fileserver.c) code
    Code:
    #include <stdio.h>
    #include <stdlib.h>                          //Added
    #include "cnaiapi.h"                 //Added
    
    int recvln(connection, char *, int);       //Added
    int readln(char *, int);                   //Added
    
    int                                        //Added
    main(int argc, char *argv[])           //Added
    {
        int        len;                 //Added
        computer comp;                               //Added
        connection  conn;                            //Added    
        FILE *fp;
        char ch;
    
        if (argc != 2) {                                                       //Added
            (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);       // Added
            exit(1);                              // Added
        }                                     // Added
    
    
        (void) printf("Chat Server Waiting For Connection.\n");     //Added
    
        /* wait for a connection from a chatclient */                //Added
    
        conn = await_contact((appnum) atoi(argv[1]));           //Added
        if (conn < 0)                           //Added
            exit(1);                         //Added
        
        (void) printf("Chat Connection Established.\n");         //Added
    
    
    
        // OPEN THE FILE => LOAD THE CONTENT OF THE FILE IN MEMORY
        fp = fopen("log.txt", "r");
        if (fp == NULL){
            printf("We were not able to open the file\n");
            exit(0);
        }
    
            (void) send(conn, fp,len, 0);  //  I NEED HELP HERE !?!?!?!?!?!?!?
    
        // PRINT THE FILE INTO THE SCREEN
        /*while (1){
            ch = fgetc(fp);
            if (ch == EOF){
                // HERE WE FOUND THE END OF THE FILE
                break;
            }
            printf("%c",ch);
        }
    
        fclose(fp);   */
        return 1;
    }

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Don't ignore any return values from your sockets or IO function calls. That means don't cast the return value to (void) for send, or anything else. Read the documentation for such functions (Google helps here, as do the man pages). If the functions fail, print a sensible error messages using perror() or strerror() & errno. This is immensely helpful for debugging.
    Code:
    if (send(conn, data, len, 0) < 0) {
        perror("send");
        // exit or return from function as appropriate.
    }
    Also note, it is conventional to return 0 from main to indicate success, or EXIT_SUCCESS. 1 typically means failure.

    In the server:
    send() doesn't magically read the contents of a FILE * and write them to the socket, just like printf(fp), would not print out the contents of the file referred to by fp. What your code does is send the contents of the fp variable (the details of the FILE struct used to maintain info about the file, not the file contents) over the socket. It's useless on the other end. Furthermore, you send len bytes, but len is uninitialized, so you may very well be asking it to send gigabytes of data, certainly an issue. You need to read from fp in a loop and send the data you read each time over the socket. Since you opened the file in text mode, I would use fgets to read a line into a buffer, then pass that buffer to send(), along with the length to write (use strlen). Examples of that are all over the web.

    In the client:
    Since the client must store the file, it must write the data it got from the server. Therefore, you should open the file in write mode: fopen("log.txt", "w").

    Oh, and those "//Added" comments really make your code annoying to read, especially since they don't line up well. I would remove them all, but if you must keep them, make sure they line up on the // part, and keep the spacing (1-2 spaces should be good) between the // and the Added the same everywhere.

    That's what I got at a quick glance. There's probably some more stuff, but that should keep you going for a while.
    Last edited by anduril462; 10-15-2012 at 09:34 PM.

  3. #3
    Registered User
    Join Date
    Oct 2011
    Location
    New Mexico
    Posts
    10
    Thanks for your help!! However I am still struggling to get it to work. Now my biggest issue is keeping the connection open after I enter the file name in the client. See code below.

    Code:
    /* make a connection to the fileserver */                   
    
        conn = make_contact(comp, (appnum) atoi(argv[2]));            
        if (conn < 0)                                 
            exit(1);                                
    
        (void) printf("Chat Connection Established.\n"); 
    
        
        /* Input File Name to use */                            
        printf ("Enter The name of the file to retrieve. \n");                
        len = readln( cname, MAX_CNAME);                           //  CODE STOPS WORKING AFTER THIS LINE!?!?!?!   
    
    
    
        // OPEN THE FILE => LOAD THE CONTENT OF THE FILE IN MEMORY
         fp = fopen("log.txt", "w");      //Here we have to open the file that  was entered to retrieve above and len instead of log.txt does not work 
        if (fp == NULL){
            printf("We were not able to open the file\n");
            exit(0);
        }
    Issue 2: What needs to be changed for this line to work at the end of fileserver to send the contents of the file to the client?
    (void) send(conn, fp,len, 0);

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    The connection should stay open so long as you don't actually close it, or change some aspect of the socket you shouldn't. It would help if you posted the complete, updated versions of your client and server code, along with any helper functions (await_contact, make_contact, etc).

    What do you mean the code "stops working" after that line? How do you know it stops working? How do you know that is the exact spot? Does it print garbage? Does it just sit there doing nothing? Does it crash? Is there any error output? You need to give a detailed description if you want detailed help.

    As for issue 2, something like:
    Code:
    char buf[1024];
    
    while (fgets(buf, sizeof(buf), fp) != NULL)
        if (send(conn, buf, strlen(buf), 0) < 0)
            // handle error
    Also, it's possible that send only sends some of the bytes, so if you read the line "Hello world", a call to send may just write "Hel". You will want to address that in the final version of your code.

  5. #5
    Registered User
    Join Date
    Oct 2011
    Location
    New Mexico
    Posts
    10
    Here are my updated versions of my client and server code.
    fileserver.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>                          
    #include "cnaiapi.h"                 
    
    int recvln(connection, char *, int);       
    int readln(char *, int);                   
    
    int                                        
    main(int argc, char *argv[])           
    {
        int        len;                 
        computer comp;                               
        connection  conn;                                
        FILE *fp;
        char ch;
            char * buffer;
            size_t result;
        
    
        if (argc != 2) {                                                       
            (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);       
            exit(1);                              
        }                                     
    
    
        (void) printf("Chat Server Waiting For Connection.\n");     
    
        /* wait for a connection from a chatclient */                
    
        conn = await_contact((appnum) atoi(argv[1]));           
        if (conn < 0)                           
            exit(1);                        
        
        (void) printf("Chat Connection Established.\n");
    
                
    
    
    
        // OPEN THE FILE => LOAD THE CONTENT OF THE FILE IN MEMORY
        fp = fopen("log.txt", "r");
        if (fp == NULL){
            printf("We were not able to open the file\n");
            exit(0);
        }
     
    
         // obtain file size:
          fseek (fp , 0 , SEEK_END);
          len = ftell (fp);
          rewind (fp);
    
          // allocate memory to contain the whole file:
          buffer = (char*) malloc (sizeof(char)*len);
          if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
    
          // copy the file into the buffer:
          result = fread (buffer,1,len,fp);
          if (result != len) {fputs ("Reading error",stderr); exit (3);}
    
    
    
        
        char buf[1024];
     
        while (fgets(buf, sizeof(buffer), fp) != NULL)
            if (send(conn, buffer, strlen(buf), 0) < 0)
            // handle error
    
           // send(conn, buffer,len, 0);                 // Needed if above while loop doesn't send the file to client? 
        //fprintf (fp, "%s", buffer);                // Needed if above while loop doesn't send the file to client? 
    
    
        /*if (send(conn, data, len, 0) < 0) {
            perror("send");
            // exit or return from function as appropriate.
        }*/
    
        // PRINT THE FILE INTO THE SCREEN
        /*while (1){
            ch = fgetc(fp);
            if (ch == EOF){
                // HERE WE FOUND THE END OF THE FILE
                break;
            }
            printf("%c",ch);
        }*/
    
        fclose(fp);   
        return 1;
    }
    fileclient.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>            
    #include "cnaiapi.h"            
    
    
    #define MAX_CNAME               10 
    #define BUFFSIZE        256                   
    
    
    int recvln(connection, char *, int);        
    int readln(char *, int);            
    
    int                                         
    main(int argc, char *argv[])            
    {
        FILE *fp;
        char ch;
        computer    comp;               
        connection    conn;               
        char            cname[MAX_CNAME];   
        int        len, received, expect;    
        char        buff[BUFFSIZE];       
    
        if (argc != 3) {                                                         
            (void) fprintf(stderr, "usage: %s <compname> <appnum>\n",        
                       argv[0]);                     
            exit(1);                             
        }                                      
    
        /* convert the compname to binary form comp */                           
    
        comp = cname_to_comp(argv[1]);                         
        if (comp == -1)                                 
            exit(1);                             
                        
    
        /* make a connection to the fileserver */                   
    
        conn = make_contact(comp, (appnum) atoi(argv[2]));            
        if (conn < 0)                                 
            exit(1);                                
    
        (void) printf("Chat Connection Established.\n"); 
    
        
        /* Input File Name to use */                            
        printf ("Enter The name of the file to retrieve. \n");                
         //len = readln( cname, MAX_CNAME);                         //This line  does not do anything for now sice we are only using 1 file (log.txt)  
    
        
        /* read and print same no. of bytes from echo server */
    
            expect = len;
            for (received = 0; received < expect;) {
               len = recv(conn, buff, (expect - received) < BUFFSIZE ?
                     (expect - received) : BUFFSIZE, 0);
                if (len < 0) {
                    send_eof(conn);
                    return 1;
                }
                (void) write(STDOUT_FILENO, buff, len);
                received += len;
            }
            (void) printf("\n");
            (void) fflush(stdout);
    
    
    
        /*// OPEN THE FILE => LOAD THE CONTENT OF THE FILE IN MEMORY
         fp = fopen("log.txt", "w");      //Here we have to open the file that  was entered to retrieve above and len instead of log.txt does not work 
        if (fp == NULL){
            printf("We were not able to open the file\n");
            exit(0);
        }*/
    
        /*if (send(conn, buff, len, 0) < 0) {
            perror("send");
            // exit or return from function as appropriate.
        }*/
    
        // PRINT THE FILE INTO THE SCREEN                         Not sure if I need this?????????????????
        while (1){
            ch = fgetc(fp);
            if (ch == EOF){
                // HERE WE FOUND THE END OF THE FILE
                break;
            }
            printf("%c",ch);
        }
    
        fclose(fp);
        return 0;
    }
    await_contact.c
    Code:
    /* await_contact.c */
    
    #include "cnaiapi.h"
    
    /*-----------------------------------------------------------------------
     * await_contact - accept a connection on port a. If no master sock is
     * already open for the port, create one and record it in the port-to-
     * socket table.
     *-----------------------------------------------------------------------
     */
    connection
    await_contact(appnum a)
    {
        struct sockaddr_in    sockaddr, csockaddr;
        int            sock, newsock, i, csockaddrlen;
        static int        p2sinit = 0;
        static struct port2sock    p2s[P2S_SIZE];
    
        cnaiapi_init();
        
        if (a == 0)
            return -1;
    
    #if defined(LINUX) || defined(SOLARIS)
        pthread_mutex_lock(&await_contact_mutex);
    #elif defined(WIN32)
        WaitForSingleObject(await_contact_mutex, INFINITE);
    #endif
    
            if (p2sinit == 0) {
                (void) memset(p2s, 0, sizeof(p2s));   
                p2sinit = 1;
            }
    
        /* look up master socket in port-to-socket table */
        for (sock = -1, i = 0; i < P2S_SIZE; i++) {
            if (p2s[i].port == a) {
                sock = p2s[i].sock;
                break;
            }
        }
    
        if (sock == -1) {
            /* open new master socket */
    
            /* look for room in p2s table */
            for (i = 0; i < P2S_SIZE; i++) {
                if (p2s[i].port == 0)
                    break;
            }
            if (i == P2S_SIZE) {
                /* no room left in p2s */
    #if defined(LINUX) || defined(SOLARIS)
                pthread_mutex_unlock(&await_contact_mutex);
    #elif defined(WIN32)
                ReleaseMutex(await_contact_mutex);
    #endif
                return -1;
            }
    
            sock = socket(PF_INET, SOCK_STREAM, 0);
            if (sock < 0) {
    #if defined(LINUX) || defined(SOLARIS)
                pthread_mutex_unlock(&await_contact_mutex);
    #elif defined(WIN32)
                ReleaseMutex(await_contact_mutex);
    #endif
                return -1;
            }
    
            (void) memset(&sockaddr, 0, sizeof(struct sockaddr_in));
            sockaddr.sin_family = AF_INET;
            sockaddr.sin_port = htons(a);
            sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
            if (bind(sock, (struct sockaddr *) &sockaddr,
                 sizeof(struct sockaddr_in)) < 0 ||
                listen(sock, LISTEN_Q_LEN) < 0) {
    #if defined(LINUX) || defined(SOLARIS)
                close(sock);
                pthread_mutex_unlock(&await_contact_mutex);
    #elif defined(WIN32)
                closesocket(sock);
                ReleaseMutex(await_contact_mutex);
    #endif
                return -1;
            }
    
            /* record master socket in table */
            p2s[i].sock = sock;
            p2s[i].port = a;
        }
    #if defined(LINUX) || defined(SOLARIS)
        pthread_mutex_unlock(&await_contact_mutex);
    #elif defined(WIN32)
        ReleaseMutex(await_contact_mutex);
    #endif
    
        csockaddrlen = sizeof(struct sockaddr_in);
        newsock = accept(sock, (struct sockaddr *) &csockaddr, &csockaddrlen);
        return newsock;
    }
    make_contact.c
    Code:
    /* make_contact.c */
    
    #include "cnaiapi.h"
    
    /*-----------------------------------------------------------------------
     * make_contact - open a new TCP connection to the specified IP address
     * (c) and port e(a).
     *-----------------------------------------------------------------------
     */
    connection
    make_contact(computer c, appnum a)
    {
        struct sockaddr_in    sockaddr;
        int            sock;
    
        cnaiapi_init();
      
        sock = socket(PF_INET, SOCK_STREAM, 0);
        if (sock < 0)
            return -1;
    
        (void) memset(&sockaddr, 0, sizeof(struct sockaddr_in));
    
        sockaddr.sin_family = AF_INET;
        sockaddr.sin_port = htons(a);
        sockaddr.sin_addr.s_addr = c;
    
        if (connect(sock, (struct sockaddr *) &sockaddr, sizeof(struct sockaddr_in)) < 0) {
    #if defined(LINUX) || defined(SOLARIS)
            close(sock);
    #elif defined(WINDOWS)
            closesocket(sock);
    #endif
            return -1;
        }  
        return sock;
    }
    I might be confusing multiple pieces of code that do the same thing in my client and server code. After the sever establishes a connection with the client (client then asks for the file name) the server closes its connection but the client stays open. This is my biggest concern right now. Then another concern is what code do I need (might already have it) that accepts the contents from the server and prints it to the terminal?

    Thanks again for all your help!!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Server sends unknown number of messages, client doesn't know when he stops
    By Phoenix_Rebirth in forum Networking/Device Communication
    Replies: 0
    Last Post: 11-21-2010, 01:48 PM
  2. Client/server shared code
    By C+/- in forum C++ Programming
    Replies: 1
    Last Post: 05-19-2007, 09:45 AM
  3. Need winsock select() client & server source code or tutorial
    By draggy in forum Networking/Device Communication
    Replies: 2
    Last Post: 06-19-2006, 11:49 AM
  4. So this is the code for the client and server
    By Bharat_kumarr in forum C++ Programming
    Replies: 14
    Last Post: 09-09-2004, 10:42 AM
  5. Code for Client/Server Socket
    By Unregistered in forum C++ Programming
    Replies: 4
    Last Post: 01-15-2002, 09:30 AM

Tags for this Thread