Avatar of BeginToLearn
BeginToLearn
 asked on

send file

I am sending a file from client to server by partition the file small part which size is 2048 and send each part . Below is my code. Please advise. tks.

FILE *fp;
       fp= fopen(t.c_str(),"r");// t is the filename string
       if(fp == NULL)
       {
            printf("error to open %s",t.c_str());
            exit(1);
       }
       fseek(fp, 0, SEEK_END);
       int size = ftell(fp);
       rewind(fp);
       int count = size/2048;
       int remainder = size %2048;
     
       char * buffer = (char*)malloc(sizeof(char) *size);
       char *p;
       p= buffer;

       // copy the file into the buffer:
       int result = fread (buffer,1,size,fp);
       
       if (result != size)
       {
            printf(" Reading error",stderr);
       }
       
       if( count >= 2048)
       {
             for( int i= 0; i < count;i++)
             {
                  send(sock, p, 2048,0);
                  p = p+2048;
             }
       
             //send the remainder trunk
             send(sock, p, remainder, 0);
       }
       else
       {
             send(sock, p, size, 0);
       }
     

Programming Languages-OtherCC++

Avatar of undefined
Last Comment
BeginToLearn

8/22/2022 - Mon
SOLUTION
Infinity08

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
can you show me how to implement it by using struct buf? i know we can use st_size to get the file size. I favor for struct stat because later i will need to use timestamp. Thanks.
Infinity08

>> can you show me how to implement it by using struct buf?

What is struct buf ?
BeginToLearn

ASKER
and using struct stat buf only save steps on calculating file size huh?
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
BeginToLearn

ASKER
struct stat buf;
       stat(t, &buf);
       size_t sz = buf.st_size;

sorry mistyping
sarabande

the file size easier can be get by stat function

#include <sys/stat.h>

   struct stat fileinfo;
   if (stat((t.c_str(), &fileinfo) != 0)
       return errno;   // file doesn't exist

   int size = fileinfo.st_size;

Sara
Infinity08

Ah, you mean struct stat.

Yes, you can use the stat function on the file to obtain a variety of information about the file :

        #include <sys/types.h>
        #include <sys/stat.h>
        #include <unistd.h>

        struct stat file_info;
        if (stat("/path/to/file", &file_info) != 0) {
            /* oops : error occurred (errno) : handle this */
        }

For more information, just check the manual page for stat :

        man stat
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
how about the rest of sending each trunk ? are they same? i just wan to shift more work to compiler :)
sarabande

oh, you asked the question while i was typing the answer :)

Sara
Infinity08

There is no standard function that splits up data into chunks and sends those chunks. You'll need to do that yourself.
Your help has saved me hundreds of hours of internet surfing.
fblack61
BeginToLearn

ASKER
tks a lot . i gonna offline for 8 hrs.srry.
Infinity08

No problem. Take your time :)

If you have any further questions about this, we'll still be here.
sarabande

you may try

       if( size > 0)
       {
             // count is the number of full chunks
             for( int i= 0; i < count;i++)
             {
                  send(sock, p, 2048,0);
                  p = p+2048;
             }
       
             //send the remainder trunk
             if (remainder > 0)
                 send(sock, p, remainder, 0);
       }


Sara
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
I think of this issue for later on. Because I gonna send many files which may have MB or GB size file and using time attribute . For example. a file is 3 GB. So the malloc and struct stat will need to allocate twice of 3GB memory.So my program will have a high chance to crash.
 That's why I want to find a way to use memory efficient hihi.
Infinity08

>> For example. a file is 3 GB. So the malloc and struct stat will need to allocate twice of 3GB memory.So my program will have a high chance to crash.

Ah, well, you don't need to read the entire file in memory at the same time.

You can read the data from the file one chunk at a time, just like you're sending it one chunk at a time.

Just do :

        fread (buffer,1,2048,fp);

(or whatever you want your chunk size to be) in the same loop where you do the send.
BeginToLearn

ASKER
i didn't think about this " You can read the data from the file one chunk at a time, just like you're sending it one chunk at a time." tks.let me modify it and work on server side then ask question again :)
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
BeginToLearn

ASKER
Do we need to send the file name and size from client to server? then create open that filename  and use file size  in for loop to write  all received trunks in to that file? Please advise. Thanks.
Infinity08

You don't need to, but you can. It all depends on the communication protocol you use/created for sending files.
BeginToLearn

ASKER
Can u take a look at my code bc I dont understand ur advise welll
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Infinity08

What code are you referring to ?

What advice are you referring to ?

What about it is it that you don't understand ?
BeginToLearn

ASKER
You said it d depend on protocol.can u elaborate more?
Infinity08

>> You said it d depend on protocol.can u elaborate more?

It depends on how you decide to send the file to the other side. If you decide to send the file name and file size, then you should send them. If you decide to do it otherwise (without sending the filename and size), then you should not send them.

It's up to you.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
BeginToLearn

ASKER
which one way is more flexible and easier to develop and change later on ? can you show me example for each way ( or link)? tks a lot.
Infinity08

Sending the file size first will help the other side to allocate enough memory if the other side needs that information. If you're just streaming the received data into a file, there's probably no need for this information.

Sending the filename will allow the other side to use the same filename for the file.

So, again : it all depends on what you want to do. One is not necessarily easier or more flexible - you just have to make a choice about how you want to do things.
BeginToLearn

ASKER
Do you have any example?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Infinity08

What do you mean ? An example of what ?

You decide on how you want to send the file (ie. the transmission/communication protocol), and then implement that.

From what I gather, you're already sending the file in chunks, so there's not much more to it than that. Just receive the chunks on the other end, and re-assemble the file. And that's it.
BeginToLearn

ASKER
Oh what I meant is without file name and its size,how the server know wgen it has receive enough number of trunks for each file
Infinity08

>> Oh what I meant is without file name and its size,how the server know wgen it has receive enough number of trunks for each file

When you stop sending.
When you close the connection.
When you send a specific "command".
etc.

Or you can just send the file size ;)

It's up to you.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
BeginToLearn

ASKER
I need to get filename, add a space, and its filesize. Server will receive it and parse to get filesize. Then apply same formula and for loop similar to the one on  client side. for each trunk receive, it will be appended on the file. Am i right? hihi
Infinity08

That sounds like a plan :)
BeginToLearn

ASKER
is that plan workable? hihi
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Infinity08

I wouldn't call it a plan if it wasn't ;)
BeginToLearn

ASKER
cool. I gonna implement it tomorrow :)
sarabande

i would suggest you first send size of filename as a 32bit integer. then the filename. then the filesize as 64bit integer. then the data.

don't use space char after filename for size check. better always make a pair of length and data.

if the filesize can be 3GB you can't use signed 32-bit integer as in the code you posted.

if the filesize can be 4GB or more you can't use (normal) stat function which only has 32bit integer for size. some compilers already use 64-bit integers in struct stat. others have functions stat64 or fstat64. same applies for fseek, ftell, fseekpos.

Sara
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
BeginToLearn

ASKER
write now i only focus on 32 bit . I have "Segmentation fault" at server side while writing trunk to file. So I need help :)
( my program is take the last file on the <string>list and send trunks of that  file to server side)    client.c server.c
BeginToLearn

ASKER
after i sent the file name, server could receive it . then it send a trunk of file, server got segmentation fault. It could display the trunk before sending. However, receiving got x) and crash
Infinity08

Where does the segmentation fault occur ?
What was the output you got ?

Are you aware that the first read you do reads 2048 bytes ? ie. it probably contains the filename, the filesize, and a part of the file.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
segmentation fault occurs right after read() in server. it read x) when i run debugger. In order to avoid client open a file to send and server append the file , i open the filename with its size such as "test.c 39".
 It could read perfect the trunk before sending. Something is wrong with receiving the trunk. However, the string of filename, space, and filesize was send sucessfully
BeginToLearn

ASKER
btw, i have updated some parts in my code. so the previous one doesn't reflect current change.
Infinity08

>> segmentation fault occurs right after read()

There are more than one read in that code. Which read are you referring to ?


>>  btw, i have updated some parts in my code. so the previous one doesn't reflect current change.

Then you might want to post that modified code ;)


Did you also see this comment in my previous post :

>> Are you aware that the first read you do reads 2048 bytes ? ie. it probably contains the filename, the filesize, and a part of the file.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
BeginToLearn

ASKER
well for testing purpose, it didn't read 2048 bytes at the first time because the file size is less than 2048.
I use
     printf("buffer is before sending : \n%s\n",buffer);
   
to reaffirm trunk content. It is ok.
and  
    printf("buffer is after receiving : \n%s\n",buffer);
--> segmentation fault.

     
here is client.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>


#include <string>
#include <iostream>
#include <list>
#include <iterator>
#include <sstream>

using namespace std;



typedef int SOCKET;

#define PORT 3490



void error(const char *msg)
{
    perror(msg);
    exit(0);
}


void list_all_files ( const string& sStartDir, list<string>& lstFound) {

   //cout << "checking " << sStartDir.c_str () << endl;

   DIR* pDir = opendir ( sStartDir.c_str ());

   if ( !pDir) return;

   dirent* pEntry;

   while ( pEntry = readdir ( pDir)) {

    // cout << "found " << pEntry->d_name << endl;

       if ( DT_DIR & pEntry->d_type && strcmp ( pEntry->d_name, ".") && strcmp ( pEntry->d_name, "..")) {

           string sSubDir = sStartDir + string ( "/") + string ( pEntry->d_name);

           list_all_files ( sSubDir, lstFound) ;

       }

       string sFound = sStartDir + string ( "/") + string ( pEntry->d_name);

       lstFound.push_back ( sFound);
   }
}

void sendFile ( SOCKET sock, list<string>& myList)
{
       cout<<" in sendFile myList size: "<<myList.size()<<endl;
     
       list<string>::iterator ptr;
       
       string t;
       
       for( ptr =myList.begin(); ptr !=myList.end(); ptr++)
       {  
              t = *ptr;
              //cout<<"t is :"<<t<<endl;
       }
         
       /*
       we will use struct stat later on because it has file timestamp attribute !!!!!!!
       struct stat buf;
       stat(t, &buf);
       size_t sz = buf.st_size; // a faster way to get filesize !!!!!!!!!!!
       
       char filechunk[2048];
       size_t count = sz/2048;
       size_t remainder = sz%2048;

       }*/

     
       
       FILE *fp;
       fp= fopen(t.c_str(),"r");// t is the filename string
       if(fp == NULL)
       {
            printf("error to open %s",t.c_str());
            exit(1);
       }
       // determine file size
       fseek(fp, 0, SEEK_END);
       int size = ftell(fp);
       rewind(fp);
       
        //using the last filename to test idea
      // add a " " then its filesize to filename then send it to server side
      // so server side can apply same formula while dealing with trunks.
      cout<<"the last t is :"<<t<<endl;

      std::stringstream tmp;
      tmp << size;
      t= t.append(" ");
      t= t.append(tmp.str());
      cout<<"t after append file size is :"<<t<<endl;
     
      char *pch = (char*)malloc(sizeof(char) *t.length() +1);
      memset(pch,sizeof(char)*t.length(),'\0');
      strcpy(pch, t.c_str());

      send(sock, pch,t.size(),0);

       // calculate  number of trunks
       int count = size/2048;
       int remainder = size %2048;
     
       char * buffer ;
       char *p;
       p= buffer;

       // read in trunk and send trunk of each file until done fo each file and move on
       int result;
       if( size >= 2048)
       {
             for( int i= 0; i < count;i++)
             {
                  buffer= (char*)malloc(sizeof(char) *2048);
                  result= fread (buffer,1,2048,fp);
                  if (result != size)
                  {
                        printf(" Reading error",stderr);
                        exit(1);
                  }
                 
                  send(sock, p, 2048,0);
             }
             
             //send the remainder trunk
             buffer= (char*)malloc(sizeof(char) *remainder);
             result= fread (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Reading error",stderr);
                   exit(1);
             }
             send(sock, p, remainder, 0);
       }
       else
       {
             buffer= (char*)malloc(sizeof(char) *size);
             result= fread (buffer,1,size,fp);
             if (result != size)
             {
                   printf(" Reading error",stderr);
                   exit(1);
             }
             printf("buffer is before sending : \n%s\n",buffer);
             strcpy(buffer, "hi");
             send(sock, p, size, 0);
       }
       fclose(fp);
     
 
       
}


int sendFileProcess(SOCKET sock)
{

       char cwd[1024];
       list<string> myList;

       memset ( cwd, '\0',sizeof(cwd));
       
        if (getcwd(cwd, sizeof(cwd)) != NULL)
      {
           printf("Current working dir: %s\n", cwd);
        }      
      else
           perror("getcwd() error");
      /*
       //display all file names in dir and subdir
       DIR *mydir = opendir(cwd);
       struct dirent *entry = NULL;
       while((entry = readdir(mydir)))
       {
            printf("entry->d_name: %s\n", entry->d_name);
       }
       cout<<endl;
       //closedir(mydir);
        */
       
       list_all_files ( cwd, myList);// this function will get all filename in a directory
             
       sendFile(sock, myList);
 
     return 1;
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[256];


    portno = PORT;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR opening socket");

    server = gethostbyname("ubuntu");

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);

    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
        error("ERROR connecting");

   
    sendFileProcess(sockfd);

    printf("Please enter the message: ");
    bzero(buffer,256);
    fgets(buffer,255,stdin);

    n = write(sockfd,buffer,strlen(buffer));
    if (n < 0)
         error("ERROR writing to socket");
   
    bzero(buffer,256);
    n = read(sockfd,buffer,255);
    if (n < 0)
         error("ERROR reading from socket");

    printf("client: %s\n",buffer);
    int t;
      if(( t= close(sockfd))== -1)
            printf("t is %d\n",t);
    return 0;
}


--------------


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 3490

void error(const char *msg)
{
      perror(msg);
          exit(1);
}

int main(int argc, char *argv[])
{
           int sockfd, newsockfd, portno;
           socklen_t clilen;
           char buffer[2048]="\0", buffer2[2048]="\0";
           struct sockaddr_in serv_addr, cli_addr;
      int n;
        int yes = 1;
   

      sockfd = socket(AF_INET, SOCK_STREAM, 0);
           if (sockfd < 0)
              error("ERROR opening socket");
           bzero((char *) &serv_addr, sizeof(serv_addr));
           

      portno = PORT;
      if(setsockopt( sockfd, SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int))== -1) {
            perror("setsockopt");
            exit(1);
        }

           serv_addr.sin_family = AF_INET;
           serv_addr.sin_addr.s_addr = INADDR_ANY;

           serv_addr.sin_port = htons(portno);
           
      if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("ERROR on binding!!!");
       
        listen(sockfd,5);
        clilen = sizeof(cli_addr);
     
      newsockfd = accept(sockfd,
                 (struct sockaddr *) &cli_addr,
                 &clilen);
           if (newsockfd < 0)
                error("ERROR on accept");
           bzero(buffer,2048);

           n = read(newsockfd,buffer,2048);
       

           if (n < 0) error("ERROR reading from socket");

           printf("Here is the message from client: %s\n",buffer);
       
        strcpy(buffer2,buffer);      
   
        //buffer contains "filename space itssize"
        // so we need to parse the buffer to get filename and its size in order to open file and write all trunks to file
       
        char seps[]= " ";
        char *token;
        char filename[300]="\0";
        char filesize[300]="\0";
       
        // establish string and get the first token
        token = strtok( buffer, seps);

        strcpy(filename,token);
        printf( "filename= %s\n",filename);

        printf( "token= %s\n",token);
        token= strtok( NULL,seps);
        strcpy( filesize, token);
        printf( "filesize= %s\n",filesize);


        FILE *fp;
        fp = fopen(buffer2, "a");// for testing purpose instead filename, just use buffer2( filename with space and its size)
        if( fp = NULL)
        {
              printf("failed to open %s to append\n",filename);
        }
        int size = atoi(filesize);
        printf("size is %d\n",size);

        // calculate  number of trunks
       int count = size/2048;
       int remainder = size %2048;
       
       // read trunks and write/append trunk of each file
       int result;
        memset(buffer,2048,'\0');
       if( size >= 2048)
       {
             for( int i= 0; i < count;i++)
             {
                  read(newsockfd,buffer,2048);
                 
                  result= fwrite (buffer,1,2048,fp);
                  if (result != 2048)
                  {
                        printf(" Writing error",stderr);
                        exit(1);
                  }
             }
             
             //remainder  of trunk
             read(newsockfd,buffer,remainder);
             result= fwrite (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Writing error",stderr);
                   exit(1);
             }
       }
       else
       {
             read(newsockfd,buffer,remainder);
             printf("buffer is after receiving : \n%s\n",buffer);
             result= fwrite (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Writing error",stderr);
                   exit(1);
             }
       }
       fclose(fp);
     
       




           n = write(newsockfd,"Message from server",18);
           if (n < 0) error("ERROR writing to socket");

      int t1, t2;
           if( t1= close(newsockfd) ==-1)
            error("ERROR in close newsockfd");
      printf("t1 is %d\n", t1);

            if( t2= close(sockfd) == -1)
            error("ERROR in close sockfd");
      printf("t2 is %d\n", t2);
           return 0;
}
Infinity08

>> to reaffirm trunk content. It is ok.

That line stops showing the buffer as soon as it encounters a '\0' character. So it does NOT guarantee that there's nothing else in the buffer.

Check the return value of read, to see how many bytes it actually read, and then show that many bytes from the buffer.
BeginToLearn

ASKER
t after append file size is :/home/ubuntu/program/test.c 319
number of bytes is read into buffer before sending is 319
--> it is correct and match with the file size on directory.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Infinity08

>> --> it is correct and match with the file size on directory.

But do the contents of the file match ?
BeginToLearn

ASKER
i can see they match clearly :)
Infinity08

Ok, then it seems you got lucky. Do check the return value of read though every time you use it.


You'll need to find out where exactly the segmentation fault occurs (you can run the code in a debugger eg.), and what the relevant variables are set to.
Your help has saved me hundreds of hours of internet surfing.
fblack61
BeginToLearn

ASKER
at server side, after i added 1 line to display number of byte receiving
 
number of byte reading into buffer at receiving is 319
buffer is after receiving :
x)
Segmentation fault


Infinity08

>>              printf("buffer is after receiving : \n%s\n",buffer);

You shouldn't use %s to show the buffer contents, because it'll keep on reading until a '\0' character is found, which might not be there.

Other than that, please follow my advice in http:#35070971
BeginToLearn

ASKER
it crashes after receiving . When i run debugger, i can see the buffer content:

(gdb) print n
$2 = 319
(gdb) print buffer
$3 = "x)\016\000P\370s\267\200\035r\000\346\032\025\000\366\032\025\000\006\033\025\000\026\033\025\000&\033\025\000\066\033\025\000F\033\025\000V\033\025\000f\033\025\000\260,\030\000P\250\025\000\226\033\025\000\246\033\025\000\266\033\025\000\306\033\025\000\326\033\025\000\300\061\032\000\366\033\025\000\006\034\025\000\026\034\025\000&\034\025\000\066\034\025\000F\034\025\000V\034\025\000P\024\030\000v\034\025\000\206\034\025\000\226\034\025\000\246\034\025\000\266\034\025\000\306\034\025\000\326\034\025\000\346\034\025\000\366\034\025\000\006\035\025\000P\371.\000&\035\025\000\066\035\025\000F\035\025\000V\035\025\000f\035\025\000v\035\025\000\206\035\025\000\226\035\025\000\246\035\025\000\266\035\025\000\306\035\025\000\326\035\025\000\346\035\025\000\366\035\025\000\006\036\025\000\026\036\025\000&\036\025\000\260\312\031\000F\036\025\000\240a"...
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
sarabande

each segmentation fault will produce a core file. when you are in debugger you can open the core file rather than debug the application. it then will point exactly to the statement that caused the crash. going up in the call stack then will show the line of your code if it isn't already your code but some system code.

Sara
Infinity08

>> it crashes after receiving

Right, we got that already.

But there's quite a bit of code after the receive.

And you'll also need to know the values of impacted variables in order to figure out what caused the crash.
BeginToLearn

ASKER
after i enable core file to unlimited and issue command:
   gdb server core

I got those info:

ubuntu@ubuntu:~/program$ gdb server core
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/ubuntu/program/server...done.
[New Thread 1897]

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /usr/lib/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./server'.
Program terminated with signal 11, Segmentation fault.
#0  0x00eafb4c in fwrite () from /lib/libc.so.6
(gdb)

---> something is wrong with fwrite huh?
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
ASKER CERTIFIED SOLUTION
sarabande

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
let me go over the code and change those suggestion
sarabande

in memset you have mixed up size and value. it must be

  memset(buffer, '\0', 2048);

the fwrite has a problem with your arguments. probably the buffer is corrupted somehow.

check all arguments in the debugger.

Sara
BeginToLearn

ASKER
A little progress after i change the code at this sugestion

first you define char pointers buffer and p

       char * buffer ;
       char *p;
       p= buffer;

after that, both buffer and p have some random value (both the same).

later you do the malloc where buffer gets a valid pointer.

but p is still invalid and you do

  send(sock, p, remainder, 0);  

for example, what could crash if p is NULL or not pointing to valid address.

-->
It can receive the content now even though it still have segmentation fault
below in the update



-----

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <dirent.h>
#include <sys/stat.h>


#include <string>
#include <iostream>
#include <list>
#include <iterator>
#include <sstream>

using namespace std;



typedef int SOCKET;

#define PORT 50000



void error(const char *msg)
{
    perror(msg);
    exit(EXIT_FAILURE);
}


void list_all_files ( const string& sStartDir, list<string>& lstFound) {

   //cout << "checking " << sStartDir.c_str () << endl;

   DIR* pDir = opendir ( sStartDir.c_str ());

   if ( !pDir) return;

   dirent* pEntry;

   while ( pEntry = readdir ( pDir)) {

     cout << "found " << pEntry->d_name << endl;

       if ( DT_DIR & pEntry->d_type && strcmp ( pEntry->d_name, ".") && strcmp ( pEntry->d_name, "..") != 0) {

           string sSubDir = sStartDir + string ( "/") + string ( pEntry->d_name);

           list_all_files ( sSubDir, lstFound) ;

       }

       string sFound = sStartDir + string ( "/") + string ( pEntry->d_name);

       lstFound.push_back ( sFound);
   }
}

void sendFile ( SOCKET sock,  list<string>& myList)
{
       cout<<" in sendFile myList size: "<<myList.size()<<endl;
     
       list<string>::iterator ptr;
       
       string t;
       
       for( ptr =myList.begin(); ptr !=myList.end(); ptr++)
       {  
              t = *ptr;
              //cout<<"t is :"<<t<<endl;
       }
         
       /*
       we will use struct stat later on because it has file timestamp attribute !!!!!!!
       struct stat buf;
       stat(t, &buf);
       size_t sz = buf.st_size; // a faster way to get filesize !!!!!!!!!!!
       
       char filechunk[2048];
       size_t count = sz/2048;
       size_t remainder = sz%2048;

       }*/

     
       
       FILE *fp;
       fp= fopen(t.c_str(),"r");// t is the filename string
       if(fp == NULL)
       {
            printf("error to open %s",t.c_str());
            exit(1);
       }
       // determine file size
       fseek(fp, 0, SEEK_END);
       int size = ftell(fp);
       rewind(fp);
       
        //using the last filename to test idea
      // add a " " then its filesize to filename then send it to server side
      // so server side can apply same formula while dealing with trunks.
      cout<<"the last t is :"<<t<<endl;

      std::stringstream tmp;
      tmp << size;
      t= t.append(" ");
      t= t.append(tmp.str());
      cout<<"t after append file size is :"<<t<<endl;
     
      char *pch = (char*)malloc(sizeof(char) *t.length() +1);

      memset(pch,sizeof(char)*t.length()+1,'\0');

      strcpy(pch, t.c_str());

      send(sock, pch,t.size(),0);

       // calculate  number of trunks
       int count = size/2048;
       int remainder = size %2048;
     
       char * buffer ;
       //char *p;
       
       //p= buffer;

       // read in trunk and send trunk of each file until done fo each file and move on
       int result;
       if( size >= 2048)
       {
             for( int i= 0; i < count;i++)
             {
                  buffer= (char*)malloc(sizeof(char) *2048);
                  result= fread (buffer,1,2048,fp);
                  if (result != size)
                  {
                        printf(" Reading error",stderr);
                        exit(1);
                  }
                 
                  send(sock, buffer, 2048,0);
                  free(buffer);
             }
             
             //send the remainder trunk
             buffer= (char*)malloc(sizeof(char) *remainder);
             result= fread (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Reading error",stderr);
                   exit(1);
             }
             send(sock, buffer, remainder, 0);
             free(buffer);
       }
       else
       {
             buffer= (char*)malloc(sizeof(char) *size);
             memset(buffer,'\0',size);
             result= fread (buffer,1,size,fp);
             printf("number of bytes is read into buffer before sending is %d\n",result);
             if (result != size)
             {
                   printf(" Reading error",stderr);
                   exit(1);
             }
             printf("buffer is before sending : \n%s\n",buffer);
             send(sock, buffer, size, 0);
             free(buffer);
       }
       fclose(fp);
     
 
       
}


int sendFileProcess(SOCKET sock)
{

       char cwd[1024];
       list<string> myList;

       memset ( cwd, '\0',sizeof(cwd));
       
        if (getcwd(cwd, sizeof(cwd)) != NULL)
      {
           printf("Current working dir: %s\n", cwd);
        }      
      else
           perror("getcwd() error");
      /*
       //display all file names in dir and subdir
       DIR *mydir = opendir(cwd);
       struct dirent *entry = NULL;
       while((entry = readdir(mydir)))
       {
            printf("entry->d_name: %s\n", entry->d_name);
       }
       cout<<endl;
       //closedir(mydir);
        */
       
       list_all_files ( cwd, myList);// this function will get all filename in a directory
             
       sendFile(sock, myList);
 
     return 1;
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[256];


    portno = PORT;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR opening socket");

    server = gethostbyname("ubuntu");

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);

    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
        error("ERROR connecting");

   
    sendFileProcess(sockfd);

    printf("Please enter the message: ");
    bzero(buffer,256);
    fgets(buffer,255,stdin);

    n = write(sockfd,buffer,strlen(buffer));
    if (n < 0)
         error("ERROR writing to socket");
   
    bzero(buffer,256);
    n = read(sockfd,buffer,255);
    if (n < 0)
         error("ERROR reading from socket");

    printf("client: %s\n",buffer);
    int t;
      if(( t= close(sockfd))== -1)
            printf("t is %d\n",t);
    return 0;
}

-----------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 50000

void error(const char *msg)
{
      perror(msg);
          exit(1);
}

int main(int argc, char *argv[])
{
           int sockfd, newsockfd, portno;
           socklen_t clilen;
           char buffer[2048]="\0", buffer2[2048]="\0";
           struct sockaddr_in serv_addr, cli_addr;
      int n;
        int yes = 1;
   

      sockfd = socket(AF_INET, SOCK_STREAM, 0);
           if (sockfd < 0)
              error("ERROR opening socket");
           bzero((char *) &serv_addr, sizeof(serv_addr));
           

      portno = PORT;
      if(setsockopt( sockfd, SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int))== -1) {
            perror("setsockopt");
            exit(1);
        }

           serv_addr.sin_family = AF_INET;
           serv_addr.sin_addr.s_addr = INADDR_ANY;

           serv_addr.sin_port = htons(portno);
           
      if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("ERROR on binding!!!");
       
        listen(sockfd,5);
        clilen = sizeof(cli_addr);
     
      newsockfd = accept(sockfd,
                 (struct sockaddr *) &cli_addr,
                 &clilen);
           if (newsockfd < 0)
                error("ERROR on accept");
           bzero(buffer,2048);

           n = read(newsockfd,buffer,2048);
   

           if (n < 0) error("ERROR reading from socket");

           printf("Here is the message from client: %s\n",buffer);
       
        strcpy(buffer2,buffer);      
   
        //buffer contains "filename space itssize"
        // so we need to parse the buffer to get filename and its size in order to open file and write all trunks to file
       
        char seps[]= " ";
        char *token;
        char filename[300]="\0";
        char filesize[300]="\0";
       
        // establish string and get the first token
        token = strtok( buffer, seps);

        strcpy(filename,token);
        printf( "filename= %s\n",filename);

        printf( "token= %s\n",token);
        token= strtok( NULL,seps);
        strcpy( filesize, token);
        printf( "filesize= %s\n",filesize);


        FILE *fp;
        fp = fopen(buffer2, "a");// for testing purpose instead filename, just use buffer2( filename with space and its size)
        if( fp = NULL)
        {
              printf("failed to open %s to append\n",filename);
        }
        int size = atoi(filesize);
        printf("size is %d\n",size);

        // calculate  number of trunks
       int count = size/2048;
       int remainder = size %2048;
       
       // read trunks and write/append trunk of each file
       int result;
        memset(buffer,2048,'\0');
       if( size >= 2048)
       {
             for( int i= 0; i < count;i++)
             {
                  read(newsockfd,buffer,2048);
                 
                  result= fwrite (buffer,1,2048,fp);
                  if (result != 2048)
                  {
                        printf(" Writing error",stderr);
                        exit(1);
                  }
             }
             
             //remainder  of trunk
             read(newsockfd,buffer,remainder);
             result= fwrite (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Writing error",stderr);
                   exit(1);
             }
       }
       else
       {
             n =read(newsockfd,buffer,remainder);
             printf("number of byte reading into buffer at receiving is %d\n",n);
           printf("buffer is after receiving : \n%s\n",buffer);
             result= fwrite (buffer,1,remainder,fp);
             if (result != remainder)
             {
                   printf(" Writing error",stderr);
                   exit(1);
             }
       }
       fclose(fp);
     
       




           n = write(newsockfd,"Message from server",18);
           if (n < 0) error("ERROR writing to socket");

      int t1, t2;
           if( t1= close(newsockfd) ==-1)
            error("ERROR in close newsockfd");
      printf("t1 is %d\n", t1);

            if( t2= close(sockfd) == -1)
            error("ERROR in close sockfd");
      printf("t2 is %d\n", t2);
           return 0;
}


⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BeginToLearn

ASKER
i got it !!! this one help me

(gdb) print fp
$4 = (FILE *) 0x0
hihihi
Infinity08

I thought you said that you verified that the received file was exactly the same as the sent file ?
sarabande

the problem is

  if( fp = NULL)

here you do an assignment and not a comparision.

change it to

  if (fp == NULL)

Sara
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
BeginToLearn

ASKER
Yesterday I fixed that if( fp = NULL) bug. Gdb help to on that :) due to  $4 = (FILE *) 0x0.Let me change the code to make it work for all files in directory and close this question and debug question
 regarding to

first you define char pointers buffer and p

       char * buffer ;
       char *p;
       p= buffer;

after that, both buffer and p have some random value (both the same).

later you do the malloc where buffer gets a valid pointer.

but p is still invalid and you do

  send(sock, p, remainder, 0);  

for example, what could crash if p is NULL or not pointing to valid address.

-->  I thought p and buffer point to the same address. when buffer and a value, p will automatically  get same value.
sarabande

no, after char * buffer; buffer has an arbitrary value where NULL has the greatest likeliness.

with p = buffer; p points to same non-valid address (there is a very small possibility that buffer and p point to a valid address in memory by accident).

for simplicity assume p == NULL

then with buffer = (char*)malloc(...  buffer has new value which is a valid address of first element of a char array in memory. but, p still is NULL !!!!

you would need either have a

   p = buffer;

after malloc or define p as reference type (c++ only);

    char * & p = buffer;

with that p is a synonym for buffer .

Sara
BeginToLearn

ASKER
i see it clearly now.tks.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.