Jrank2013
Jrank2013

Reputation: 138

File Comes Corrupted Using SFML TCP Sockets and packtes

I'm writing code to for a client to connect to a server and the server to respond and send a .exe file. I am using the SFML networking library to write my code. I can successfully send the file with the correct size but the wrong md5sum which means something is getting changed but i can't figure out where. Here is my code can someone spot my mistake. Sever:

#include <SFML/Network.hpp>
#include  <string>
#include <iostream>
#include <fstream>
#include <vector>

int main()
{
    std::string i{ "Hello World" };
    sf::Packet packet;
    //packet << i;
    sf::TcpListener tcpl;
    sf::TcpSocket tcps;
    std::vector<std::string> Buffer;
    std::string tmp;

    std::ifstream fis("C:\\Users\\Cyber Security\\Documents\\Repos.git\\Agent\\x64\\Debug\\Project1.exe", std::ios::in |    std::ios::binary);



    tcpl.listen(5050);

    std::cout << "Listening" << std::endl;

        tcpl.accept(tcps);

    while (std::getline(fis,tmp))
    {
        Buffer.push_back(tmp);
    };

    packet << static_cast<sf::Uint32>(Buffer.size());
    for (std::vector<std::string>::const_iterator it = Buffer.begin(); it != Buffer.end(); ++it)
        packet << *it;
    sf::Socket::Status status = tcps.send(packet);
    if (status == sf::Socket::Error)
        std::cout << "Error";
    fis.close();
    std::cout << "Packet Sent" << std::endl;

    tcpl.close();

    std::cout << "Socket Closed" << std::endl;

    system("pause");
    return 0;
}

Client:

#include  <SFML/Network.hpp>
#include <string>
#include <fstream>
#include <vector>
#include <iostream>
int main()
{
    std::string h{ "" };
    sf::Packet packet;
    sf::TcpSocket tcps;
    sf::Uint32 size = 0;
    std::vector<std::string> Buffer;

    sf::TcpSocket::Status status= tcps.connect("10.10.10.10", 5050);
    std::ofstream fis;
    if (status == sf::TcpSocket::Status::Done)
    {
        fis.open("Project1.exe", std::ofstream::binary);
        std::cout << "Starting Donwload of Packet" << std::endl;
        status== tcps.receive(packet);
        if (status == sf::Socket::Error)
            std::cout << "Error";
        std::cout << "Packet Received" << std::endl;
    }




        packet >> size;
        for (sf::Uint32 i = 0; i < size; ++i)
        {
            std::string item;
            packet >> item;
            Buffer.push_back(item);
        }
     for (std::vector<std::string>::const_iterator it = Buffer.begin(); it != Buffer.end(); ++it)
        fis << *it;

    fis.close();



    system("pause");
    return 0;
}

Upvotes: 1

Views: 301

Answers (1)

nvoigt
nvoigt

Reputation: 77354

Your file is a binary file. It's not a number of strings. Reading it as such is already missing bytes, even without sending it over a network. Treat your file as a sequence of bytes:

#include <SFML/Network.hpp>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

int main()
{
    sf::Packet packet;
    sf::TcpListener tcpl;
    sf::TcpSocket tcps;

    std::ifstream fis("C:\\Users\\Cyber Security\\Documents\\Repos.git\\Agent\\x64\\Debug\\Project1.exe", std::ios::binary);

    std::vector<char> fileContents((std::istreambuf_iterator<char>(fis)), std::istreambuf_iterator<char>());

    fis.close();

    tcpl.listen(5050);

    std::cout << "Listening" << std::endl;

    tcpl.accept(tcps);

    packet << static_cast<sf::Uint32>(fileContents.size());

    for (std::vector<char>::const_iterator it = fileContents.begin(); it != fileContents.end(); ++it) packet << *it;

    sf::Socket::Status status = tcps.send(packet);

    if (status == sf::Socket::Error)
        std::cout << "Error";

    std::cout << "Packet Sent" << std::endl;

    tcpl.close();

    std::cout << "Socket Closed" << std::endl;

    system("pause");
    return 0;
}

Client:

#include  <SFML/Network.hpp>
#include <string>
#include <fstream>
#include <vector>
#include <iostream>

int main()
{
    sf::Packet packet;
    sf::TcpSocket tcps;
    sf::Uint32 size = 0;

    sf::TcpSocket::Status status = tcps.connect("10.10.10.10", 5050);

    if (status == sf::TcpSocket::Status::Done)
    {
        std::cout << "Starting Download of Packet" << std::endl;

        status == tcps.receive(packet);

        if (status == sf::Socket::Error)
            std::cout << "Error";

        std::cout << "Packet Received" << std::endl;
    }

    std::ofstream fos("Project1.exe", std::ofstream::binary);

    packet >> size;

    for (sf::Uint32 i = 0; i < size; ++i)
    {
        char item;
        packet >> item;
        fos << item;
    }

    fos.close();

    system("pause");
    return 0;
}

The client is still missing a lot of error handling, but it's POC code anyway.

Upvotes: 2

Related Questions