0

I have a simple server written in Java, that just sends an Integer to a connected client. I have a client written in C, that connects to the server and prints out the received Integer.

My problem is that the result varies. About half of the times executing the client I get the correct result (234), but other times I get 8323072.

This is the server:

class TCPServer {
  public static void main(String args[]) throws Exception {
     ServerSocket welcomeSocket = new ServerSocket(6789);

     while(true)
     {
        Socket connectionSocket = welcomeSocket.accept();
        System.out.println("welcomeSocket.accept() called");
        DataInputStream inFromClient = new DataInputStream(connectionSocket.getInputStream());
        DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

        outToClient.writeInt(234);
     }
  }

}

And this is the client:

int main(int argc, char *argv[])
{
    if(argc != 4){
        printUsage();
        return;
    }

    char* serverIP = argv[1];
    char* serverPortC = argv[2];
    char* integerToSendC = argv[3];

    int serverPort = atoi(serverPortC);
    int integerToSend = atoi(integerToSendC);

    int socketDesc = socket(AF_INET, SOCK_STREAM, 0);

    if(socketDesc < 0) {
        printf("Error when creating socket\n");
        return;
    } 

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(serverPort);
    inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);

    int connection = connect(socketDesc, (struct sockaddr*) &serverAddr, sizeof serverAddr);

    if(connection < 0) {
        printf("Error when establishing connection\n");
        return;
    }

    char intBuffer[4];

    if(recv(socketDesc, intBuffer, sizeof intBuffer, 0) == -1){
        printf("Error while receiving Integer\n");
    }

    int receivedInt = ntohl(*((int *) &intBuffer));

    printf("Received int: %d\n", receivedInt);

    close(socketDesc);
}

Thanks in advance for any help!

Edit: So in the end I did something like this, just for anybody who has the same problem:

while(receivedBytes < 4){
    int readBytes = read(receiverSocket, &intBuffer, (sizeof intBuffer) - receivedBytes, receivedBytes);
    receivedInteger += (intBuffer << (8*receivedBytes));
    receivedBytes += readBytes;
}
8
  • 1
    Could possible be because of how many bytes are assigned for int in Java and C and their associated sub-boundaries. Try sending small numbers. If Java assigns 4 bytes for int, C assigns 2 bytes. So the range is way less in C Commented Apr 20, 2013 at 7:04
  • that number is 2**16 * 127 (i.e. the third byte all 1's, the bottom two all 0's) Commented Apr 20, 2013 at 7:08
  • @LittleChild I would have thought so too, but DataOutputStream.writeInt seems pretty clear on sending four bytes, at least in the 32bit runtime. Commented Apr 20, 2013 at 7:09
  • Your cast looks dreadful, not to mention a prime place for a bus error on non-intel hardware. Have you considered just reading into a int32_t instead. ? Commented Apr 20, 2013 at 7:14
  • 1
    The value returned after ntohl() is 0x7F0000. I.e. 127 is ending up in the third octet. I'm curious to know what it looked like before the ntohl() It almost seems you're sometimes only getting partial reads, but even then I would have expected to see at least a 0xEA somewhere in there Odd. Commented Apr 20, 2013 at 7:30

2 Answers 2

1

Can you be sure you have received sizeof intBuffer bytes on the client side? No you can not, as recv() might return less bytes then requested.

Mod you code to loop around recv() as long as less bytes then requested have been received and no error occurred.

Note that recv()ing 0 bytes indicates the connection had been closed by the other side.

Also make sure the server side sends in network byte order.

Also^2: It is good idea to initialise variables (intBuffer here), at least during the development phase, will say: prior to the tuning phase.

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

4 Comments

It doesn't expain the received value: 123 maps to 00 00 00 7B on network. The received value 8323072 is 7F 00 00 00. Even if 1 byte is read, it should not be 7F.
@ValeriAtamaniouk: Most propably the other side hung up the connection, recv() returned with 0, so no error message is logged and the 8323072 being printed out for receivedInt is simply garbage as intBuffer was not initialised prior to having been passed to recv().
could be, but this doesn't exactly match the counter-part sources: the DataOutputStream shell send 4 bytes before close.
Thank you for the hint, looping around read() and taking care of the received bytes finally made it work!
-1

Your problem could be because of the sub-boundaries of the various data types.

In Java, 4 bytes are assigned to int and 2 bytes for a short.
In C, 4 bytes are for long and 2 bytes for int.

This means Java int -> C long and Java short -> C int.
Now it depends on where your priorities lie.

If you want to perform an intense mathematical calculation in Java and send the result over socket to C, I recommend you do Java int -> C long or
If you want to just send small numbers and have the intense calculation done in C, do the Java short -> C int conversion.

Hope that helped.

6 Comments

In C, in my computer, 4 bytes for int.
See DataOutputStream.writeInt. It appears writeInt always writes 4 bytes in big-endian. So long as it is reassembled correctly on the C side as a 4-byte int I would expect this to be correct.
@WhozCraig I do not program in C. I was just referring to the size of basic data types on Wikipedia and it says that C assigns 16 bits (2 bytes) Hence my answer. If there are mistakes in the answer or if it is wrong in the first place, let me know. I will delete it right away so as not to confuse the OP
@LittleChild The size of an int in C depends on your compiler settings and target architecture. It can definitely be 32 bit, and the OP seems to indicate that, in his case, it is
The minimum size per the standard (C99 §5.2.4.2.1) of a compliant int is 16 bits (15+1sign). But the standard only mandates the value representations as minimum compliance requirements. Nearly every non-embedded C compiler today uses at least 32bit int, some 64bit. Wiki likely only lists the standard minimum requirement.
|

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.