QByteArray different on Linux and windows??



  • Hi All,

    So I am trying out a file transfer from linux to windows using QTcpSocket.

    I read the file in small "chunks" on the linux machine and append a checksum to the end of each chunk. Only when the receiving computer receives the data and and finds the checksums to match, do I send the the next chunk. If I send over a text file, it comes through perfectly except when there are special characters. When I try and send an image file, it is corrupted even though the checksums always match perfectly.

    Below is a snippet of how I send my info across the socket. I have removed some of the overhead, such as checking the data read from the file is valid and open file is successful and such. I stripped it down to show the basics:

    @
    void AddCHSM(QByteArray &In)
    {
    unsigned int CHKSM = 0;
    for (int i = 0; i < In.size(); i++)
    {
    CHKSM += (unsigned int)In[i];
    }
    char CheckSumMSB= (char)(CHKSM >> 8);
    char CheckSumLSB = (char)CHKSM;
    In.append(CheckSumMSB);
    In.append(CheckSumLSB);
    }

    void SendChunkFunction()
    {
    int ChunkSize = 2500;
    QByteArray FileContents;
    QFile *Filer = new QFile("tree.jpg");

    FileContents = Filer->read(ChunkSize);
    AddCHSM(FileContents);
    Sock->write(FileContents);
    }@

    On the receiving side:

    @
    bool CheckCHSM(QByteArray ArIn)
    {
    unsigned int CHKSM = 0;
    for (int i = 0; i < ArIn.size()-2; i++)
    {
    CHKSM += (unsigned int) ArIn[i];
    }
    char CheckSumMSB = (char)(CHKSM >> 8);
    char CheckSumLSB = (char)CHKSM;
    char ReceivedCheckSumMSB = (char) ArIn[ArIn.size()-2];
    char ReceivedCheckSumLSB = (char) ArIn[ArIn.size()-1];

    if ((CheckSumLSB == ReceivedCheckSumLSB) && (CheckSumMSB == ReceivedCheckSumMSB) )
        return true;
    
    return false;
    

    }

    void DataReceived()
    {
    QByteArray Ar;
    Ar = Sock->readAll();
    if (CheckCHSM(Ar))
    {
    //Good message received
    Ar = Ar.left(Ar.size()-2);

    QFile *File = new QFile("tree.jpg");
    if(!File->open(QIODevice::ReadWrite))
    {
    Sock->write(FATAL_ERROR);
    return;
    }
    File->seek(File->size());
    File->write(Ar);
    File->close();
    Sock->write(GOOD_DATA_RECEIVED);
    }

    @

    Once again I have stripped the code down to its bare essentials. I currently make sure the file is empty at the beginning of the code, so the problem is not that I have rogue information in the file before starting.

    I compare the two files in Notepad++ after running the code and they are the same size and look like they have the same characters. The file header is correct. But the are a few characters different.

    Are there any ideas as to what is happening?

    Thank you for your help!

    Jermcb



  • QByteArray is just a bucket-o-bytes and behaves identically on Linux and Windows.

    You are assuming incorrectly that bytes written in one function call are received as one block at the other end. This is not the case the vast majority of the time and should never be relied on.

    For example, if you read the first 200 bytes of the 2500 sent the last two bytes, incorrectly assumed to be the checksum, are unlikely to match, skipping thwrite to file, and discarding the data. The next call to DataReceived() will start from byte 201 and will also fail. You need to buffer received data until you have a potentially complete block before testing its integrity.

    It's also unclear what "In" is in the sender and how it relates to "Sock"



  • Hi ChrisW67,

    I apologize for omitting the declaration of the "Sock" variable.
    It is:
    @QTcpSocket *Sock = new QTcpSocket();@

    The variable "In" is a reference to the QByteArray passed to the function.
    @void AddCHSM(QByteArray &In)@

    As I mentioned, I have in my code some error checking which I have omitted from this post for ease of reading. In the code I first read a chunk from the file. I then send a command over the socket stating a new chunk is ready for transmission, along with the expected chunk size. I then compare the size of the data I read from the socket. If the sizes do not match up or the checksum does not match, I send an error message and repeat the process until I get it correct. So far this has worked well. Except for my problem.

    I am trying this method with a sufficiently small image and I step through the process on both computers in debug mode. It seems to work well except my windows pc seems to interpret the QByteArray differently than it should when writing to the file.

    Does anyone else have any ideas?

    Thanks in advance!



  • Bytes in one end of the TCP pipe will come out the other exactly as sent. No interpretation involved.

    What do you mean by "except my windows pc seems to interpret the QByteArray differently"? QByteArray does not interpret the bytes: it's just a bucket. What is applying an interpretation to the bytes? Nothing in your code except the checksum function (BTW take a look at qChecksum() ) interprets the bytes, and that function does not modify them.

    What do you mean by, "and look like they have the same characters"? Either the files are identical or they are not. Have you run an md5sum or similar on them to confirm exact equality? What exactly is the difference? If they are identical what is the issue?

    Opening a binary file (a JPEG) in a text editor is unlikely to give you identical results on different platforms; at the very least the interpretation the text editor places on carriage return and line feed characters is problematic.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.