Thread: Send a message after sending a file via socket

  1. #1
    Registered User
    Join Date
    Mar 2019
    Posts
    5

    Send a message after sending a file via socket

    Hello,
    I made a program that transfers a JSON file using the client's socket to the server. In fact, I wanted to send a message after receiving the file from the server to the client but apparently there is a problem that is wrong, so the message does not arrive at the client. Can you help me please. Here are the source codes:
    server.c
    Code:
    #include <ctype.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <json-c/json.h>
    #include <netinet/in.h> 
    #include <pthread.h>
    #include <stdio.h> 
    #include <stdlib.h>
    #include <string.h> 
    #include <stdarg.h>
    #include <sys/mman.h> 
    #include <sys/stat.h>
    #include <sys/socket.h> 
    #include <unistd.h> 
    #include "jsmn.h"
     
    #define BUFFER_SIZE          1024
    #define MARGE_PROGRESSION     100
    #define BUFFER_SIZE_JSON   100000
    #define MAX_TOKEN_COUNT       128
     
    pthread_t        th_server;
    pthread_cond_t   cond_sr;
    pthread_mutex_t  verrou_sr;
     
    /***********************************************************************
     * Main.c: 
     **********************************************************************/
    int main(int argc, char *argv[]) 
    { 
      FILE* fichier_sr;
      int   socket         = 0;
      int   size_line, desc_write;
      long  fichier_size   = 0, size_avanc_sr = 0;
      char* fichier_sr_nom = "server_test.json";
      char* line_buf       = (char *) malloc (BUFFER_SIZE*sizeof(char));
      char* Msg_to_cl      = (char* )malloc(BUFFER_SIZE*sizeof(char));  
            Msg_to_cl      = "hello from server\n";  
      pthread_mutex_init (&verrou_sr, NULL); 
      pthread_cond_init (&cond_sr, NULL);
     
      fichier_sr   = fopen(fichier_sr_nom,"w");
      socket       = attente (socket, argv[1]);
      fichier_size = lire_taille_fich(socket, fichier_size);   
     
      pthread_create(&th_server,NULL,thread_pourcentage_server,NULL);
     
      while((size_line = recevoir_fichier(size_line,socket, line_buf)) >= 0) 
      { 
        if (size_line == 0) 
    	{
    	  break;
    	}
    	desc_write = ecrire_fichier(desc_write,size_line,fichier_sr,line_buf);
    	size_avanc_sr += size_line;
    	pthread_mutex_lock(&verrou_sr);
    	result_server=100*((float)(size_avanc_sr)/(float)(fichier_size));
    	pthread_mutex_unlock(&verrou_sr);
    	pthread_cond_broadcast(&cond_sr);
        usleep(100000);
     
    	if (desc_write < size_line)
    	{
    	  perror("File write failed on server.\n");
    	}
      }
      pthread_join(th_server, NULL);   
      pthread_mutex_destroy (&verrou_sr);
      pthread_cond_destroy (&cond_sr); 
      fclose(fichier_sr);
      //parseJSON(fichier_sr_nom);
      send(socket,Msg_to_cl,BUFFER_SIZE,0);
      return 0;
    }
    


    client.c
    Code:
    #include <arpa/inet.h>
    #include <stdio.h> 
    #include <unistd.h>
    #include <sys/socket.h> 
    #include <stdlib.h> 
    #include <netinet/in.h> 
    #include <string.h> 
    #include <sys/stat.h>
    #include <pthread.h>
     
    #define BUFFER_SIZE      1024
    #define MARGE_PROGRESSION 100
     
    pthread_t        th_client;
    pthread_cond_t   cond_cl;
    pthread_mutex_t  verrou_cl;
     
    /***********************************************************************
     * Main.c: 
     **********************************************************************/
    int main(int argc, char *argv[]) 
    {  
      FILE*    fichier_cl;
      int      socket = 0;
      long     size_file     = 0, size_avanc_cl = 0;
      char*    line_str      = NULL;
      char*    file_name     = "client_file.json";
      char*    Msg_from_sr   = (char* )malloc(BUFFER_SIZE*sizeof(char));            
      size_t   line_pos      = 0;
      ssize_t  desc_line;
     
      pthread_mutex_init (&verrou_cl, NULL); 
      pthread_cond_init (&cond_cl, NULL);
     
      fichier_cl = fopen(file_name,"r");
      size_file  = taille_fich(file_name);
     
      socket     = connecte(socket,argv[1],argv[2]);
      socket     = envoyer_taille_fich(socket,size_file);
      pthread_create(&th_client,NULL,thread_pourcentage_client,NULL);
     
      while ((desc_line = getline(&line_str, &line_pos, fichier_cl)) != -1) 
      {
        if((socket = envoyer_fich(socket,line_str)) < 0) 
    	{
    	  printf("ERROR: Failed to send file %s.\n", file_name);
    	  break;
    	}
    	size_avanc_cl += strlen(line_str);
    	pthread_mutex_lock(&verrou_cl);
    	result_thread=100*((float)(size_avanc_cl)/(float)(size_file));
    	pthread_mutex_unlock(&verrou_cl);
    	pthread_cond_broadcast(&cond_cl);
        //usleep(100000);
     
        if (line_str)
        {
        free(line_str);
        }
        line_pos = 0;  
      }
      pthread_join(th_client, NULL);   
      pthread_mutex_destroy (&verrou_cl);
      pthread_cond_destroy (&cond_cl);
      fclose(fichier_cl);
      read(socket, Msg_from_sr, 100);
      return 0; 
    }


  2. #2
    Registered User
    Join Date
    Feb 2019
    Posts
    6
    Hi alquds ,

    my recommendation.
    Take the easy way and use the libcurl communication library instead of so many includes and socket programming.
    It might save you a lot of time.
    Regards
    Sennenmut

  3. #3
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    On a side note, you are not checking to see if malloc failed, or freeing that memory when you are done with it.

    It's also a good idea not to cast malloc, because it hides if you've forgotten to include stdlib
    Fact - Beethoven wrote his first symphony in C

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Click_here View Post
    It's also a good idea not to cast malloc, because it hides if you've forgotten to include stdlib
    Huh?!

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by flp1969 View Post
    Huh?!
    comp.lang.c FAQ list - Question 7.7b: What's wrong with casting malloc's return value?

    Basically, it's the old default int return type (and parameters) rearing its ugly head. As compilers begin to phase it out with respect to the newer versions of the C standard, this will become a non-issue. But not yet.
    Last edited by laserlight; 03-26-2019 at 07:07 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    I still don't see the problem casting malloc() result... Suppose that a pointer is 64 bits long and an int is 32 bits long (I32LP64, as on SysV ABI for x86-64).

    sizeof(char *) > sizeof(int):

    Since you forgot to declare the prototype (or include stdlib.h), malloc(), probably it will be interpreted as:
    Code:
    int malloc(int);
    If you don't cast the result of the call, than int will be sign extended, giving you the wrong address. If you cast the result, the address can be sign extended or not, it is still the wrong address (upper 32 bits zeroed or all set).

    sizeof(char *) < sizeof(int):

    Now, let's suppose we are compiling for a microcontroller with limited memory and this particular hypotetical compiler works with addresses only 12 bits long (4 KiB of memory, max), and int is 16 bits long (int is longer than a pointer)... The result will be zero extended, giving you the right address if no casting is used... but it will also give you the right address if casting is used (it will cut upper 4 bits)...

    sizeof(char *) == sizeof(int)

    int and pointer have the same size (i386 mode on x86 arch, for instance)... Both casting and no casting works the same, giving you the right pointer...

    In all 3 cases the compiler warns you about the lack of a prototype... what's being "hidden"?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by flp1969
    In all 3 cases the compiler warns you about the lack of a prototype... what's being "hidden"?
    That's not guaranteed: if you're not compiling with respect to C99 or later, the compiler is not required to warn about the lack of a prototype, whereas it will almost certainly warn about the conversion from int to pointer type. This was mentioned at the end of the FAQ I linked to.

    EDIT: come to think of it, compilers might not be required to warn even post-C99, but I think we can be reasonably sure that they would warn at higher warning levels, whereas with a cast pre-C99 there should be no warning at the highest warning levels.

    In conclusion, the important part is to #include <stdlib.h> when using malloc, and compile at high warning levels. Since the cast of the return value of malloc is not needed and opens this possibility of accidentally leaving out the include without a warning, there's no point using it unless you really need your C code to be compilable as C++. This is after all just a secondary point to this thread.
    Last edited by laserlight; 03-26-2019 at 11:41 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It is also false to assume that all pointer types are the same size and have the same representation.
    Question 5.17

    C only supports the T* -> void* -> T* round-trip conversion.

    Motorola 68000 - Wikipedia
    One compiler I used long ago returned pointers in address registers, and integers in data registers.
    If malloc were prototyped as int, then as Indiana Jones would say, "You're digging in the wrong place".

    And don't forget good ole DOS, with it's 16-bit integers and 32-bit "far" pointers.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    @OP
    Code:
      char* Msg_to_cl      = (char* )malloc(BUFFER_SIZE*sizeof(char));  
            Msg_to_cl      = "hello from server\n";  
    ...
      send(socket,Msg_to_cl,BUFFER_SIZE,0);
    1. You have a memory leak through the second assignment.
    2. Msg_to_cl no longer points to a block of memory BUFFER_SIZE in length.

    > so the message does not arrive at the client.
    How do you know?
    You neither check the result of the send() at the server, nor the result of the read() at the client.


    And in general, if you want people to actually try your code (rather than make vague guesses), then you should post something that compiles.
    Short, Self Contained, Correct Example
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Salem View Post
    It is also false to assume that all pointer types are the same size and have the same representation.
    Question 5.17
    All pointers have the same size, but maybe not the same representation. On x86-64 the linear address space allows only 48 bits addresses, sign extended if bit 47=1, but the pointers sizes are always 64 bits.

    Quote Originally Posted by Salem View Post
    C only supports the T* -> void* -> T* round-trip conversion.
    There is no such "roundtrips". Casting is only a reinterpretation of a type, specially pointers. Here:

    Code:
    int a[] = { 1, 2, 3 };
    long *p = (long *)a;
    int * isn't "converted" to void * then to long *...

    Quote Originally Posted by Salem View Post
    Motorola 68000 - Wikipedia
    One compiler I used long ago returned pointers in address registers, and integers in data registers.
    This is a good point... But remember you are assigning an integer to a pointer variable. When derreferencing this pointer, the compiler will create code that uses A0~A7 registers, instead of D0~D7... Or you were using a bad compiler...

    Quote Originally Posted by Salem
    If malloc were prototyped as int, then as Indiana Jones would say, "You're digging in the wrong place".
    Nobody is saying malloc() should be declared as returning int... The argument is that in abscence of a prototype the compiler could interpret the return type of this unprototyped function as int. My point is: casting the result of malloc or not, prototyped or not, will do the same thing...

    Quote Originally Posted by Salem
    And don't forget good ole DOS, with it's 16-bit integers and 32-bit "far" pointers.
    If you don't have the proper prototype for malloc(), the good old DOS app could fail anyway, casting or not... Probably won't fail because malloc() is one of those "intrinsic" functions (concept introduced by Microsoft C 6.0 in mid-90's and adopted by Borland).

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > All pointers have the same size, but maybe not the same representation. On x86-64 the linear address space allows only 48 bits addresses, sign extended if bit 47=1, but the pointers sizes are always 64 bits.
    Did you even BOTHER to read the link, which specifically states examples which refute your bold assertions?

    You keep banging on about how x86 does it.
    The world isn't a VAX.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Salem View Post
    >Did you even BOTHER to read the link, which specifically states examples which refute your bold assertions?

    You keep banging on about how x86 does it.
    Yes, I did... Did you read the text? It talks about representation of pointers. Nothing is said abour actual pointer sizes.

    A pointer is a simple integer (not saying it's type is int!), the only difference from "normal" integers is how operators (+, - and * [indirection]) behave... So, in C, all pointers have the same size (except when qualified, for exemple, by far or near keywords [x86 real mode])... How the processor will deal with this integer (pointer) or how the compiler will create the binary object code (as you all like to cite, here) is "implementation dependent".

    I am citing x86 because it is the machine I have NOW. But I worked with lots of architectures before, including DOS, VAX/VMS, AmigaDOS, ... and other Unices.

    My example, citing x86-64 mode, was about the 48 bits representation of the linear address in a 64 bits pointer... It was just an example...

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by flp1969
    A pointer is a simple integer (not saying it's type is int!), the only difference from "normal" integers is how operators (+, - and * [indirection]) behave...
    I daresay Salem's link points out that a pointer isn't necessarily a "simple integer" with operators that have pointer semantics: the example is that of a null pointer not necessarily having the numeric value of zero.

    Quote Originally Posted by flp1969
    So, in C, all pointers have the same size (except when qualified, for exemple, by far or near keywords [x86 real mode])... How the processor will deal with this integer (pointer) or how the compiler will create the binary object code (as you all like to cite, here) is "implementation dependent".
    As far as I can tell, the C standard really doesn't mandate that all pointers have the same size, or even that all pointers to object types have the same size. Integer types have different sizes, so even by analogy that doesn't in itself preclude different pointer types from having different sizes.

    Anyway, this seems to be rather academic: alquds doesn't appear to be doing any kind of pointer to one object type to pointer to another object type conversions, much less pointer to function type to pointer to object type or vice versa conversions. It is just Click_here's recommendation about malloc concerning allowing the implicit conversion from pointer to void to pointer to object type, and that tallies with traditional advice, and doesn't require a downgrade from best practice even when compilers warn by default about the lack of a function prototype for malloc. It's not worth arguing about, unless you absolutely have a good argument (besides C++ compatibility) as to why a cast should be best practice instead.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Mar 2019
    Posts
    5
    Thank you for your answer, but the problem is not about the dynamic allocation or the malloc cast, elsewhere I used char buffer [buffer_size] and the problem remains the same. My main subject is when I send a mesage after the transfert of file, the server receives a empty message

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Like I said earlier in direct response.
    You're not checking return results.

    > send(socket,Msg_to_cl,BUFFER_SIZE,0);
    You're sending 19 bytes of valid data, and 1005 bytes of garbage.
    Assuming that you don't actually step off the end of memory and the program dies with a segmentation fault before then.

    Run both in separate debugger instances, and put breakpoints on the final send/recv.
    What result do they return?
    What value is errno ?

    Maybe you managed to put one of the sockets into non-blocking mode. Who knows, most of your code is missing.


    Have you prototyped very simple client/servers to test your ideas?
    Client
    send + recv

    Server
    recv + send

    Can you send just one message on a round trip successfully?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Socket Message only receive / Not Send (Pthread Issue)
    By sergioms in forum C Programming
    Replies: 3
    Last Post: 07-17-2018, 07:49 AM
  2. Use one socket to send and receive message (using UDP)
    By tanya9x in forum C++ Programming
    Replies: 11
    Last Post: 02-28-2010, 05:58 AM
  3. Send() not "sending" whole message
    By Martin_T in forum C Programming
    Replies: 9
    Last Post: 11-18-2009, 07:37 PM
  4. socket message sending and receiving problem
    By black in forum C Programming
    Replies: 5
    Last Post: 01-15-2007, 04:46 AM
  5. Who is using a file/How to send a message
    By leonel in forum Windows Programming
    Replies: 0
    Last Post: 01-31-2003, 01:54 PM

Tags for this Thread