0

I'm trying to transfer a file using sockets from a C++ application to a Java application. I wrote this simple code in C++ to send the file:

int main() {
    int sock;
    struct sockaddr_in sa;
    char* memblock;

    /* Create socket on which to send. */
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock < 0) {
        printf("opening datagram socket");
        exit(1);
    }

    /* Construct name of socket to send to. */
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(0x7F000001);
    sa.sin_port = htons(4444);

    /* Send messages. */
    FILE *file;
    unsigned long fileLength = 0;

    file = fopen(FILE_PATH, "rb");
    if (!file) {
        printf("Error opening the file.\n");
        return 1;
    }

    // Get file length.
    fseek(file, 0, SEEK_END);
    fileLength = ftell(file);
    printf("File length is: %d.\n", fileLength);
    fseek(file, 0, SEEK_SET);

    memblock = (char*)malloc(sizeof(char)*fileLength);
    if (memblock == NULL) {fputs ("Memory error",stderr); exit(2);}

    // copy the file into the buffer:
    int result = fread(memblock, 1, fileLength, file);
    if (result != fileLength) {fputs ("Reading error", stderr); exit(3);}

    int pos = 0;
    char* pMemblock = memblock;
    while (pos < fileLength) {
        int sent = sendto(sock, pMemblock, 80, 0, (struct sockaddr*)&sa, sizeof sa);
        if (sent < 0)
            printf("Error sending datagram message.\n");
        else printf("Sent %d.\n", sent);
        pos += 80;
        pMemblock += 80;
    }

    delete memblock;
    fclose(file);

    close(sock);
    return 0;
}

On the Java side this is how I write down data received:

while (true) {
                receiveData = new byte[300];
                receivedPacket = new DatagramPacket(receiveData, receiveData.length);
                serverSocket.receive(receivedPacket);
                try {
                    fou = new FileOutputStream(<filename>, true);
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                }
                fou.write(receivedPacket.getData(), 0, 80);
                fou.close();
            }

The result is that the file I receive is correct to a certain point, but it is not complete. Is there anything wrong in my code wither in the Java or in the C++ part? Thanks!

2
  • 1
    Did you tried to instead of using UDP use TCP? Just to make sure no packages are being lost Commented Feb 23, 2011 at 10:58
  • I'm trying that because that was my doubt as well. But... is it possible to lose packets even when the communication is within the same system? Thanks! Commented Feb 23, 2011 at 11:12

2 Answers 2

4
  • UDP doesn't guarantee that all datagrams will arrive.
  • UDP doesn't guarantee that all datagrams will arrive only once.
  • UDP doesn't guarantee that the datagrams that do arrive will be in the sequence that you sent them.

See here.

You are wrong to assume that these rules do not apply just because your sender and receiver are on the same machine.

UDP without any form of additional reliability and sequencing is simply the wrong choice for what you want to do.

You should use TCP (or another reliable transport) rather than UDP.

Sign up to request clarification or add additional context in comments.

3 Comments

You're perfectly right. My assumption was clearly wrong. It's working now. Thanks!
Make sure that your TCP code is written with the assumption that each read will return between 1 and the size of the buffer bytes and NOT the size of data you happen to 'know' that you are sending in each send call in the other program. Otherwise it will 'work' until you need to show it to someone important ;)
And to get decent performance... You probably want to set your SO_RECVBUF socket option to increase the size of the receiver's buffer and/or the TCP Window size (probably platform specific but setting SO_RECVBUF will adjust the TCP Window size on Windows platforms). Though this may not have much effect if both ends are always on the same machine...
0

Just by looking over your code, the problem probably is, that you're write statement is wrong:

fou.write(receivedPacket.getData(), 0, 80);

which should be:

fou.write(receivedPacket.getData(), 0, receivedPacket.getLength());

Another note: are you closing the FileOutputStream intentionally within the while loop (therefore every time you execute the loop? (this is not really wrong but slower)

1 Comment

receivedPacket.getLength() always equals 80, I checked that. The problem is that the number of packets arrived is lower that the number of packets sent, it seems. I'm closing it inside just because this is a test, and I don't know what may happen in case I close my application inside the loop without having closed the file. In my final code it will sure be different. Any other idea why I may be receiving less packets? Thanks for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.