Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] Sending binary files over TCP  (Read 6963 times)

0 Members and 1 Guest are viewing this topic.

jValdron

  • Newbie
  • *
  • Posts: 5
    • View Profile
[Solved] Sending binary files over TCP
« on: September 23, 2011, 06:14:59 pm »
Hi there,

My question might not be directly related to SFML, however, I use SFML for all my networking needs.

I'm currently trying to implement an update function that would require sending binary files over TCP. The problem is, with binary files, they always get corrupted. I can transfer text files correctly.

Here is an example of the code used in the server:
Code: [Select]

std::ifstream File(Filename, std::ios::in | std::ios::binary | std::ios::ate);

// Here I got some code to send the filename and size before sending packets

File.seekg(0, std::ios::beg);
EncryptedPacket ToSend; // EncryptedPacket is the same as the one used in the tutorials, for now
Buffer = new char[4096];
while(File.read(Buffer, sizeof(Buffer)))
{
    ToSend.Clear(); // Clear the previous packet
    ToSend << Buffer; // Add the 4096 bytes we just read to the packet
    Socket.Send(ToSend); // Send the packet
    std::fill(Buffer, Buffer + sizeof Buffer, 0); // Clear the buffer
}
File.close();
delete[] Buffer;


And here is the code used in the client to write the packets into a file:
Code: [Select]

OutputFile.open(Filename, std::ofstream::binary); // Open a new file for writing, filename comes from the server

while(true)
{
    EncryptedPacket Received;
    Client.Receive(Received);
    std::string Buffer;
    Received >> Buffer; // Read the buffer from the packet
    OutputFile.write(Buffer.c_str(), sizeof(Buffer)); // Write the buffer to the file
}


I've tried sending PNG, MP4 and TAR files, without success.

Here is an example of the original PNG file header:
http://www.zimagez.com/zimage/screenshot-230911-120853pm.php

And here is an example of the transfered PNG file header:
http://www.zimagez.com/zimage/screenshot-230911-121142pm.php

If you need a complete working example, I could write one.

Thanks for your help, I've tried a lot of different things...[/img]

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
[Solved] Sending binary files over TCP
« Reply #1 on: September 23, 2011, 06:51:48 pm »
Code: [Select]
ToSend << Buffer
This code writes Buffer as a C-style string, so it stops after the first '\0'.

A simple fix:
Code: [Select]
ToSend << std::string(Buffer, Buffer + sizeof(Buffer));

But a better strategy would be to simply get rid of sf::Packet, it's useless here since you send raw data. No type or endianness is involved.
Code: [Select]
while (File.read(Buffer, sizeof(Buffer)))
{
    Socket.Send(Buffer, sizeof(Buffer));
}

Code: [Select]
while(true)
{
    char Buffer[4096];
    std::size_t Size = 0;
    Client.Receive(Buffer, sizeof(Buffer), Size);
    OutputFile.write(Buffer, Size);
}


By the way, you don't need a dynamic allocation for Buffer.
Code: [Select]
char Buffer[4096];

You don't need to clear the buffer, but rather use the number of bytes actually read from the file -- but I don't remember how it is done with std::istream.

Don't forget to check the result of socket functions (Send, Receive) for failure or disconnection.
Laurent Gomila - SFML developer

jValdron

  • Newbie
  • *
  • Posts: 5
    • View Profile
[Solved] Sending binary files over TCP
« Reply #2 on: September 23, 2011, 08:08:03 pm »
Once again, you've saved the day Laurent. Thanks for the additional tips also. Merci!