Sending image

This is a discussion on Sending image within the Networking/Device Communication forums, part of the General Programming Boards category; When i send a text file everything is fine. When i try to send a .gif it gives me the ...

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    822

    Sending image

    When i send a text file everything is fine.
    When i try to send a .gif it gives me the correct size but goes into a loop and sending the same 11 bytes.

    I open the files in binary mode so it cant be the problem.
    I got a hunch that it should meet an EOF character or such but i dont check for that so i dont know what could be the problem.

    Client sending:
    Code:
    void Send_File()
    {
         //***************************************
         //Read file and send size
         //***************************************
         ifstream file("1.gif", ios::binary);
         char cLength[256] = {0};
         unsigned int nBytesSent = 0, fileSize = 0, r = 0;
         // get length of file:
         file.seekg (0, ios::end); fileSize = file.tellg(); file.seekg (0, ios::beg);
         // allocate memory:
         char * buffer = new char [fileSize];
         // read data as a block:
         file.read (buffer,fileSize);
         file.close();  itoa(fileSize, cLength,10);
         send(inetsock, cLength, strlen(cLength), 0);
         //******************************************
         //Send data
         //******************************************
         char *buf = new char[256];
         cout <<  "fileSize "  <<  fileSize  << endl;  system("pause");
         while(nBytesSent<fileSize)
         {
               string str(buffer); //char* to string
    
               strcpy(buf, str.substr(nBytesSent, 255).c_str());
               r = send(inetsock, buf, strlen(buf), 0);
               if (r==SOCKET_ERROR)
               {
                   cout << "Connection unexpectedly closed \n"; closesocket(inetsock);
               }
               nBytesSent+=r;
               cout << "nBytesSent " << nBytesSent  << endl;
    
         }
         delete[] buffer; delete[] buf;
    }
    Server recieving:
    Code:
    void Recieve_File()
    {
       //Recieve size
          char recvBuff[256]={0}; string fileBuff="";
       unsigned int fileSize = 0,    nBytesRecieved = 0,  r = 0;
          recv(AcceptSock, recvBuff, sizeof(recvBuff), 0);
       fileSize=atof(recvBuff);
       //cout << fileSize << endl; system("pause");
       //******************************************
       //Recieve data
       //******************************************
          char *buf = new char[256];
          cout << "fileSize "       << fileSize  << endl;
       while(nBytesRecieved<fileSize)
       {
             memset(buf, 0, 256);
             r=recv(AcceptSock, buf, sizeof(buf), 0);
             fileBuff.append(buf);
             nBytesRecieved+=r+1;
             cout << "nBytesRecieved " << nBytesRecieved  << endl;
    
       }
       //cout << fileBuff << endl; system("pause");
       ofstream TheCopy("TheCopy.txt",ios::binary | ios::app);
       TheCopy.write (fileBuff.c_str(),fileSize);
       TheCopy.close();
       delete[] buf;
    }
    Last edited by Ducky; 08-09-2009 at 06:57 AM.
    Compiler MSVC++ 2013 with Code::Blocks.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    There's a lot of strlen() on char arrays which will contain embedded \0 characters.

    The whole convert it to a C++ style string, and then back again is a waste of time.

    See my previous reply to your other thread on how to send the whole lot in one loop.

    Also,
    Sending the length in advance is good, but it needs to be a fixed-width record of some sort.
    How will you tell say "123" from "12345656"?

    It kind of works at the moment because all GIF files begin with "GIF", so working out the end of the number isn't a problem.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    Ok, thank you Salem, i'll try to implement your code.

    "How will you tell say "123" from "12345656"?"

    You mean that when i send the size there could be other characters attached to it?
    Compiler MSVC++ 2013 with Code::Blocks.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    Not exactly.
    How will you tell the end of the number from the start of the file?

    Doing
    send(inetsock, cLength, strlen(cLength)+1, 0);
    would ensure there was a recognisable delimiter between the length and the file.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    Ah ok i see it now.

    Your code is working like a charm.

    Only i still have a problem with images. It gets transfered but it must get corrupted because
    there is no image on openning. Though the size is the same.

    I didnt change the recieving side maybe there is a function there that mess up things.

    This is the sending part edited with your code:
    Code:
    void Send_File()
    {
         //***************************************
         //Read file and send size
         //***************************************
         ifstream file("1.gif", ios::binary);
         char cLength[256] = {0};
         size_t nBytesSent = 0, fileSize = 0, r = 0;
         // get length of file:
         file.seekg (0, ios::end); fileSize = file.tellg(); file.seekg (0, ios::beg);
         char * buffer = new char [fileSize];
         // read data as a block:
         file.read (buffer,fileSize);
         file.close();  itoa(fileSize, cLength,10);
         send(sock, cLength, strlen(cLength)+1, 0);
         //******************************************
         //Send data
         //******************************************
         while ( fileSize )
         {
                 int num_sent = send( sock, buffer, fileSize, 0 );
                 if ( num_sent > 0 )
                 {
                      fileSize -= num_sent;
                      buffer   += num_sent;
                 }
         }
         delete[] buffer;
    }
    Last edited by Ducky; 08-09-2009 at 08:19 AM.
    Compiler MSVC++ 2013 with Code::Blocks.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    > recv(AcceptSock, recvBuff, sizeof(recvBuff), 0);
    This probably contains the length, and the first part of the file.

    Look at the received length of data.
    Extract the file size information, and save the rest to the file.

    Storing the received data fragments in a temp array is a waste of effort IMO.
    You may as well just save the fragments to a file.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    > recv(AcceptSock, recvBuff, sizeof(recvBuff), 0);
    "This probably contains the length, and the first part of the file."

    No, i checked it, it only contains the size.

    "Storing the received data fragments in a temp array is a waste of effort IMO.
    You may as well just save the fragments to a file."

    I just changed this and changed
    nBytesRecieved += r+1; to nBytesRecieved += r; and now its working.

    Thanks a million Salem!
    Last edited by Ducky; 08-09-2009 at 01:09 PM.
    Compiler MSVC++ 2013 with Code::Blocks.

  8. #8
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    Quote Originally Posted by Salem View Post
    There's a lot of strlen() on char arrays which will contain embedded \0 characters.

    The whole convert it to a C++ style string, and then back again is a waste of time.

    See my previous reply to your other thread on how to send the whole lot in one loop.

    Also,
    Sending the length in advance is good, but it needs to be a fixed-width record of some sort.
    How will you tell say "123" from "12345656"?

    It kind of works at the moment because all GIF files begin with "GIF", so working out the end of the number isn't a problem.
    For the fixed length thing, just do what I do.

    string bob = "%57092370$";
    string number = bob.substr(bob.find("%",0),bob.find("$",0)-bob.find("%",0));

    Then just convert number to an int and your good!

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    Thank you Azjherben!

    But how would you know what the delimiter characters would be?

    By the way any idea why is this working perfectly on one computer but when i put them on a lan its not.

    On the sender side all data are sent. At least thats what the cout<< says that i put in the loop.

    On the reciever side, first it recieves the right number of bytes to recieve but then it gets nothing.

    If i give the command to send it again it will recieve the command itself, the number of bytes to send and the data too but all within the number of bytes to send so the end of the data
    isnt there anymore, because the command itself and the number of bytes to send takes up about 4 bytes in the beginning.
    Last edited by Ducky; 08-10-2009 at 06:02 AM.
    Compiler MSVC++ 2013 with Code::Blocks.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    > But how would you know what the delimiter characters would be?
    Anything you like, so long as you can identify it as being a delimiter, and not part of the first block of data, and not part of the 2nd block of data.

    You treat the data as a byte stream.
    Finite-state machine - Wikipedia, the free encyclopedia
    For each byte, you should be able to specify exactly 1 state or 1 transition, like
    - isLengthChar
    - isDelimiter
    - isImageChar
    If you can't uniquely identify where you are, then your protocol is broken.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  11. #11
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    Are you saying to have just one recv() on the recieving size and then separating the file size from the data?

    Yes this is good when you know what will be the data.

    But when the data starts with a number, how would you know what number is the size of the file and what is the data?

    By the way i changed the recieving side of the code just like you showed me on the sending side.

    Now when i dont send the size (i compile the size in it) its working.
    When i send the size of the file it looks like after the first recv() function got the size it continues waiting and not passing on to the next recv() function.
    Compiler MSVC++ 2013 with Code::Blocks.

  12. #12
    Registered User
    Join Date
    Mar 2009
    Posts
    76
    Quote Originally Posted by Ducky View Post
    Thank you Azjherben!

    But how would you know what the delimiter characters would be?

    By the way any idea why is this working perfectly on one computer but when i put them on a lan its not.

    On the sender side all data are sent. At least thats what the cout<< says that i put in the loop.

    On the reciever side, first it recieves the right number of bytes to recieve but then it gets nothing.

    If i give the command to send it again it will recieve the command itself, the number of bytes to send and the data too but all within the number of bytes to send so the end of the data
    isnt there anymore, because the command itself and the number of bytes to send takes up about 4 bytes in the beginning.


    I had a simular problem.
    Becuase, I made a program just like this one, it recived it correctly, except it added a few extra characters to the end of the new file.

    I'll go find that code now.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    > Are you saying to have just one recv() on the recieving size and then separating the file size from the data?
    You can't rely on the fact that if you send say 6 bytes that you will ALWAYS receive those 6 bytes (by themselves) in a single recv call.

    TCP only sees the stream, and delivers the stream in order.
    How individual packets arrive is completely arbitrary.

    It's YOUR job to sort out the stream of bytes into something meaningful, and one way to do that is to send recognisable delimiters.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  14. #14
    Registered User
    Join Date
    Dec 2007
    Posts
    822
    If its so then whats the point in sending the size of the file?

    And btw isnt send(sock, cLength, strlen(cLength)+1, 0); suppose to send it in the 3 argument?

    And why would it work perfectly on one computer (im using 192.168.1.2 not 127.0.0.1), even for bigger files?


    @azjherben

    You intrigue me. Im interested.
    Compiler MSVC++ 2013 with Code::Blocks.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,854
    > If its so then whats the point in sending the size of the file?
    Well if you're only sending just the one file, probably not a lot.

    But if you were browsing a web page for example, then multiple things would need to be sent.


    > And btw isnt send(sock, cLength, strlen(cLength)+1, 0); suppose to send it in the 3 argument?
    Huh?
    With just strlen(), then "123\0" would be sent as "123"
    Adding 1 means "123\0" gets sent (a useful delimiter in it's own right)
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 05:17 AM
  2. Replies: 1
    Last Post: 05-27-2009, 01:46 PM
  3. Simple Image Processing
    By ejohns85 in forum C++ Programming
    Replies: 4
    Last Post: 03-19-2009, 01:10 PM
  4. Image rotation - doesn't always work
    By ulillillia in forum C Programming
    Replies: 12
    Last Post: 05-03-2007, 01:46 PM
  5. Replies: 4
    Last Post: 03-02-2003, 09:12 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21