Search code examples
javac++socketstcptcpserver

TCP-Server sending a file in a packet structure (to a non Java client)


Me asking one of those questions again :P
Since I'm porting my C++ server to a Java server (and it's nearly done) I'm missing only one thing:
Sending files.
I can't wrap my head around on how to construct the packet in Java to send it via DataOutputStream.
In C++ I prepared the packet in this way (first 4bytes reserved for the file_size, rest the file itself):

char *pData = new char[file_size];

memcpy(pData, charArray.data(), file_size);

char *packet = new char[file_size + 4];
memset(packet, 0, file_size + 4);

*(int*)(packet) = file_size;
memcpy((char*)(packet + 4), pData, file_size);

int r = file_size + 4;
sendall(stream, packet, &r);

I hope you can help me out here, I'm able to construct simple packets but this one is giving me a headache :P
Do I merge the bytes or how would I accomplish the C++ code in Java x..x
Thanks in advance!

sendall func:

int sendall(TCPStream *s, char *buf, int *len)
{
    int total = 0;
    int bytesleft = *len;
    int n;

    while(total < *len)
    {
        n = s->send(buf+total, bytesleft);
        if (n == -1) break;
        total += n;
        bytesleft -= n;
    }

    *len = total;

    return n ==-1 ? -1 : 0;
}

Solution

  • The Java equivalent of that C code is:

    int file_size = ...;
    byte[] file_data = ...;
    
    byte[] packet = new byte[file_size + 4];
    ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN).putInt(file_size);
    System.arraycopy(file_data, 0, packet, 4, file_size);
    

    You need to confirm whether the file size was sent with high or low byte first, and change to BIG_ENDIAN if needed.

    Since C code just added file size as int, and was likely run on Intel processor, the result was LITTLE_ENDIAN, which is why I specified that in the code above. But as @paulsm4 said, you should test this.