0

I am writing an UDP-based streaming server and encountered a strange problem, I am sure it's just a simple error, but I cannot find a solution. The server does something along the lines of:

FILE* infile = fopen(inf, "rb");
register int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int16_t buffer[LENGTH+HEADER];
struct header header;
int16_t data[LENGTH];
uint32_t number = 0;

/*set socket options etc. */

while(!feof(infile)){
    fread(data, 1, LENGTH, infile);
    /* if i write the contents of data to a file here, the error below occurs*/
    fwrite(data, 1, LENGTH, testfile);
    /*create a header, encode everything with htons/htonl*/


    if(sendto(sock, buffer, LENGTH+HEADER, 0, (struct sockaddr*) &to,
                    sizeof to) < 0)
         /*die*/            
}

This seems to work. I can decode it and the data is not corrupt. However, I wrote a test client that works(or rather: does not work) as follows:

struct sockaddr_in si_other, si_me;
register int s;
unsigned int slen = sizeof(si_other);
int16_t buf[LENGTH+HEADER];
int16_t data[LENGTH];
FILE* file = fopen(of, "wb");

/*open socket, set options, etc. */

while(1){
    if(recvfrom(s, (char *)buf, LENGTH+HEADER, 0, (struct sockaddr*) &si_other,
                 &slen) < 0)
        /*die*/    
    decode(buf, data);
    /* If I write the decoded data to a file here, the error below occurs */
    fwrite(data, 1, LENGTH, testfile);
    if(is_empty(data) == 0){
        printf("End signal received.\n");
        break;
    }
} 

Now to my problem. When I inspect the test files in hex with diff <(xxd test_before) <(xxd test_after), I get this(example diff line):

< 03d5ff0: f3fd f3fd 99fe 99fe 40ff 40ff e7ff e7ff  ........@.@.....
---
> 03d5ff0: f3fd f3fd 0000 0000 0000 0000 0000 0000  ................

Which means that the last 12 bytes of the packets' data are lost. Everything else is fine.

This is only test code, so it is not as important(I guess), but it is weird and I want to know why.

Any ideas?

EDIT:

I have now tried a few approaches from the answers, thus far without getting anywhere. I will keep trying.

EDIT 2:

The code works on a different machine. I am not sure what the problem was, but it seems to work for anyone but me. Sorry for stealing your time and thank you for all the kind suggestions on how to improve the code and such!

Thanks in advance, Carson

hellerve
  • 508
  • 1
  • 6
  • 30
  • 1
    If you want to send/receive `LENGTH+HEADER` number of int16_t's, you'll have to pass `(LENGTH+HEADER)*sizeof(int16_t)` to sendto/recvfrom. (or in this particular case just `sizeof buffer`) – nos Oct 01 '14 at 14:03
  • BTW: Don't do this: `while(!feof(infile)){` feof() works different from what you think; it returns nonzero *after* a failed read operation. – wildplasser Oct 01 '14 at 14:45
  • The functions encode() most likely changes the length of the data, especially if there is a key post pended to the data. The sendto() and recvfrom() functions, as written in your code, are not taking this byte count change into account. Your code is giving u16 counts for length when it should be 2*u16 counts. – user3629249 Oct 02 '14 at 07:40

3 Answers3

2

You are casting a 2 bytes buf to char and read half of it contains.

recvfrom(s, (char *)buf, LENGTH+HEADER, 0, (struct sockaddr*) &si_other,
             &slen) 

The buf array has (LENGTH+HEADER) * 2 bytes and you read half of it

Use char arrays for both send and receive.

EDIT

This the way to read the file:

unsigned char data[LENGTH];

fseek(inf, 0, SEEK_END);
int file_Size = ftell(inf);
fseek(inf, 0, SEEK_SET);
if(file_Size  > LENGTH){
    //file larger than data
}
fread(data, sizeof(unsigned char), file_Size, inf);
  • Sorry, that code was in for debugging purposes. I removed it and tested again(also tried what you suggested). It does not change anything. The packets are 536 bytes long so that doesn't really explain the loss of the last 12 bytes. – hellerve Oct 01 '14 at 13:47
  • @Carson When using *fread* check first the length of file and read it all without the while loop. That is the purpose of *fread*. Check if you read the whole file before sending. – γηράσκω δ' αεί πολλά διδασκόμε Oct 01 '14 at 13:51
  • that on the other hand does not explain why the bytes get sent, but not received. – hellerve Oct 01 '14 at 13:58
2

Your code is very incomplete, so it is difficult to say anything for certain. How is the data put in int16_t buffer[LENGTH+HEADER] on the sending side? What do the decode and encode functions look like?

One obvious hazard I can see is that your buffers are of type uint16_t, which is two bytes. The functions sendto() and recvfrom() expect the buffer length in bytes. In other words, your buf is double the length (in bytes) that you actually tell sendto(). Thus your encoding function might make some data disappear, from the pov of the send/receive.

Wild guess, 12 bytes missing might be a suitable 4 byte value or other data htonl() processed and then lost in send.

Post a more complete code, for better guesses.

thuovila
  • 1,960
  • 13
  • 21
0

As noted in Edit 2, the code works on all machines I tested the code on but mine. I am not sure what the problem was/is, but it seems to work for anyone but me. Sorry for stealing your time and thank you for all the kind suggestions on how to improve the code and such!

hellerve
  • 508
  • 1
  • 6
  • 30