Thread: send/recv binary files using sockets in C++

  1. #1
    Registered User
    Join Date
    May 2004
    Posts
    1

    send/recv binary files using sockets in C++

    Hi everyone, first post

    Just thinking of an algorith that i could use to send two binary files, such and an .mp3 or .avi file over a network connection to a client machine.

    I know you can just use a buffer, but how are you supposed to work out the size of the file for the recv() function? is there a null character or an EOF flag for binary files?

    I'm really after generic ways of doing this as i plan to try and make the client easily portable to any other standard C++ compiler on linux/BSD/win etc.

    can anyone help me out here?

    thanks

    dafat

  2. #2
    Registered User
    Join Date
    May 2004
    Posts
    19
    Code:
     
    char * buffer;     //buffer to store file contents
    long size;     //file size
    ifstream file (filename, ios::in|ios::binary|ios::ate);     //open file in binary mode, get pointer at the end of the file (ios::ate)
    size = file.tellg();     //retrieve get pointer position
    file.seekg (0, ios::beg);     //position get pointer at the begining of the file
    buffer = new char [size];     //initialize the buffer
    file.read (buffer, size);     //read file to buffer
    file.close();     //close file
    hope this helps.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I know you can just use a buffer, but how are you supposed to work out the size of the file for the recv() function?
    First you send the length, then you send the data

    > is there a null character or an EOF flag for binary files?
    No, but you don't need such a thing if you've already got a length
    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.

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    You could have a fixed length buffer (i.e. 512 or 1024 bytes). Then read the file (buffer length) bytes at a time and send it that way. On the other side, it doesn't really matter how big the buffer is. Just receive as much as you can (check the return of recv()), and write to the new file the number of bytes you received.

    And yeah, you find the file size and do what Salem said about sending the file length first (i.e. a standard long header).
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    One key you need to remember is that the receiver needs to know the length of the data before it starts receiving it via socket. Now how you implement the server and the data transfer protocol is arbitrary.

    Kuphryn

  6. #6
    Registered User
    Join Date
    Jul 2002
    Posts
    47

    What I did

    When I wrote my first file transfer socket program I did it like this.

    NOTE: I had to make the server interface with VisualBasic sockets for someone which made this a bit more complex.

    I first got the file size which is seen in previous posts
    Then I sent this.
    s:filename:size
    This told the other end I was sending a file with the name filename and the size of size.
    Once the client approved the transfer I would have a 512block buffer and send the data prefixed with a command like this.
    d:data
    d:data2
    d:data3
    etc...
    the d told the client it was data that was meant to be applied to the file.
    Just to make sure the client knew the server was finished at the end I would send EOF without the d:
    that way the client knew it was not to be applied to the file but that it had reached the end.

    I hope that helps.

  7. #7
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    On mine, I looked up the FTP protocol. Kind of a neat idea, you don't need the header thing... just open up a second socket connection, continuously send data until EOF, then close the socket (shutdown() and wait with recv() until the client closes the socket, then closesocket()). The client receives data until the socket is closed.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  8. #8
    Registered User
    Join Date
    Jul 2002
    Posts
    47
    that works to... :-D

    I tend to try and be very memory efficient and prefer keeping only one socket open because that is all that I really need.

  9. #9
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>I tend to try and be very memory efficient
    I know what you mean. I was like that too, but a year of counselling helped me get over it. I still have relapses sometimes though

    That was my original plan in my program, but then I decided against it. Especially because you have to ensure that you receive all the bytes in each packet (make sure you receive the entire packet before receiving the next), which can be a pain. Opening a new socket, you just write whatever you receive, without worrying about how much you've received - and the client's buffer size doesn't even have to match the server's.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  10. #10
    Registered User
    Join Date
    Jul 2002
    Posts
    47
    I can still verify because of judging by how many bytes I receive.
    If it matches the buffer I sent than its ok. Because the client knows the buffer size it can determine if all the data was transmitted or not.

    Another side note.
    One reason I am so memory efficient like is because SCO sucks at MEMORY management and sometimes I have to write programs at work to run on SCO. For example...You can't have a buffer size greater than 255 bytes, otherwise the system has a memory dump. I HATE SCO

  11. #11
    Registered User
    Join Date
    Jul 2004
    Posts
    2
    I also am attempting to copy files this way.
    How is your progress going? Care to share how you
    have accomplished this goal?

  12. #12
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Code:
    std::ifstream file1("in.txt", ios::in | ios::binary);
    std::ofstream file2("out.txt", ios::out | ios::binary);
    
    char input;
    while(file1.read(&input, 1))
    {
       file2.write(&input, 1);
    }
    
    file1.close();
    file2.close();
    or
    Code:
    CopyFile("in.txt", "out.txt", FALSE);
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  13. #13
    Registered User
    Join Date
    Jul 2004
    Posts
    2
    This is what I have so far.

    Code:
    /*------------------| CopyAFileViaSocket |----------------------------------------------*
    |	Description:
    |	~~~~~~~~~~~
    |   Loads a file into a buffer and sends piece by piece it via a socket object 
    |	until complete. This process consists of handshaking with the Server connected
    |	to via the socket. 
    |	
    |	The server must accept the following protocol.
    |
    |	1. Send "FC"			: This tells the server that we are attemping a filecopy.
    |	2. Recv "OK"			: If we receive this from the server we know to proceed.
    |	3. Send std::string		: Now we send the name of the file.
    |	4. Recv "OK"			: If we receive this from the server we know to proceed.
    |	5. Send unsigned long	: Now we send (char buffer) the size of the file in bytes.
    |	6. Recv "OK"			: If we receive this from the server we know to proceed.
    |	7. Send bytes			: Now we enter a loop sending bytes until filesize is sent.
    |
    |
    |	Parameters:
    |	~~~~~~~~~~~
    |
    |	Return Codes:
    |	~~~~~~~~~~~~
    |   
    \*-------------------------------------------------------------------------------------*/
    bool CopyAFileViaSocket(std::string Source)
    {
    	/* open file for reading in binary mode */
    	std::ifstream infile;
        infile.open(Source.c_str(), std::ios::in | std::ios::binary);
    	if (infile.fail() == 1)
    	{
    		infile.close();
    		return false;
    	}	
    	
    	/* File Size */
    	struct stat FileInfo;
    	unsigned long iFileSize = 0;
    	if (stat(Source.c_str(), &FileInfo) == 0)
    	{
    		iFileSize = FileInfo.st_size;
    	}
    
    	/* set cursor to the beginning of the file */
        infile.seekg(0, std::ios::beg);
    
    	/* Since we are copying a file over the network we need to use a small buffer */
    	char   buf[1024];
    
    	while (!infile.eof())
        {
          infile.read (buf, sizeof(buf));
    	   //Socket->write(buf,infile.gcount());
        }    
    
    	infile.close();
    	return true;
    }

  14. #14
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    So what's the problem? If the problem is just that you don't know how to use WinSock, read some tutorials (like http://cboard.cprogramming.com/showthread.php?t=41926)
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  15. #15
    Registered User
    Join Date
    Jul 2004
    Posts
    9
    if you want to send binaries and still want to use text, i would suggest uuencode/uudecode. it converts binaries in text and vice versa. try the man pages

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. added start menu crashes game
    By avgprogamerjoe in forum Game Programming
    Replies: 6
    Last Post: 08-29-2007, 01:30 PM
  2. Copying Binary Files
    By mikeman118 in forum C++ Programming
    Replies: 9
    Last Post: 08-11-2007, 10:55 PM
  3. Processing binary or plaintext files
    By Jags in forum C Programming
    Replies: 12
    Last Post: 08-04-2006, 02:35 PM
  4. Linking header files, Source files and main program(Accel. C++)
    By Daniel Primed in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2006, 11:46 AM
  5. Binary files in C++
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 09-25-2001, 04:48 PM