tags:

views:

154

answers:

5

Hi!

I'm building a client and a server program that exchanges data over TCP and I'm having trouble sending an ACK-confirmation from the server back to the client when an operation is successfull. I've managed to send a struct with various members from the client to the server, then the server should respond by sending an integer confirming the ID of the struct back to the client.

In server.c I have this function:

int sendACK(int socket, int ack_int){

    int com_result;
    int ACK = htonl(ack_int);

    printf("\n\tSending ACK with value: %i", ack_int);

    com_result = send(socket, &ACK, sizeof(ACK), 0);

    if (com_result == -1) {
     perror("\n\t[ERROR] Send ACK");
     return 0;
    }

    return 1;

}

This function is called by another function in server.c like this:

int ACK = myStruct->ID;
sendACK(socket, ACK);

So, if I have just recieved a struct with ID: 2, the output will be:
Sending ACK with value: 2

In client.c I recieve the ACK like this:

int ACK = 0;
data_size  = sizeof(myStruct.ID);
com_result = read(client_socket, &ACK, data_size);
ACK = ntohl(ACK);

if (com_result == -1) {
    perror("\n\t[ERROR] Read");
} else {
    printf("\n\tRecieved %i of %i bytes", com_result, data_size);
    if (ACK != myStruct.ID) {
     printf("\n\t[ERROR] Invalid ACK (%i).", ACK);
    }
}

But the ACK is always recieved with a value of 1, so the output from client is:
Recieved 4 of 4 bytes
ERROR] Invalid ACK (1).

Why isn't the integer recieved with a value of 2, and how may I fix this?

A: 

You should never send whole values like this, you need to pay more attention to serialization. This might fail if, for instance, the sizeof (int) is different on the sending machine from the receiving one, in which case you will read the incorrect number of bytes.

It's better to take more care and serialize fields one byte at a time.

unwind
+1  A: 

In order to debug it, you can use wireshark. Execute wireshark and set its options to listen to the required port. You will see what was actually sent inside the packet through the network. This will allow you to understand if the problem is with the server, the client or both.

eyalm
A: 

I can't figure out anything wrong with the code you pasted above. I'd suggest getting out Wireshark, or another socket tracing program, and looking at the bits on the wire.

brianegge
+3  A: 

This is most likely not the problem, but I believe that the 2nd line in your client.c snippet below should be sizeof(ACK).

int ACK = 0;
data_size  = sizeof(ACK); // was: sizeof(myStruct.ID);
com_result = read(client_socket, &ACK, data_size);
ACK = ntohl(ACK);

Also, depending on your data flow, is it possible that you're actually reading correctly and the ACK is the response from a packet which you sent previously?

Nicholaz
I suspect that this is the cause of the problem. Even if it isn't it is still plain wrong.
Dipstick
Just ran through the code and found a rogue call to sendACK earlier in the programme which was transmitting a 1-value to the client. Thanks:)
Orolin
A: 

I'd check that your main sender/receiver code is handling the correct amount of data.

If your sender sends 20 bytes followed by a four byte ACK but the receiver only reads 16 before trying to read the ACK, you could have this sort of problem.

If you're sending variable length data (ie. with a bytecount prefix) a common confusion about whether the bytecount being transmitted actually includes the additional bytes required to send the byte count...

Roddy