1

I'm trying to get a C99 client to communicate with a Java server. However the data being received by the Java server is not the same as the data that was transmitted. (ie. @x�@Ófl/ú.��@¨�����������������Û¢ÁBp‘ˇ¡`Ôfl/)

I've contemplated that it's an encoding issue however I've hit a brick wall. I've tried testing the two programs to conclude that the Java server is able to communicate with a Java client and the C client is able to communicate with a C server.

However I cannot get the Java server to communicate with a C client.

Java code:

serverSocket = new ServerSocket(port);  
Socket sock = serverSocket.accept();                               

BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

String inputString = in.readLine();
System.out.println(inputString);

C code:

struct sockaddr_in sin;
struct hostent *host;

host = gethostbyname(hostname);

bzero(&(sin.sin_zero),8); 
sin.sin_port = htons(port);
sin.sin_addr = *((struct in_addr *)host->h_addr);
sin.sin_family = AF_INET;

sock = socket(AF_INET, SOCK_STREAM, 0);

if(connect(sock, (struct sockaddr *)&sin,sizeof(struct sockaddr_in)) == -1)

...

send(sock, &message, strlen(message)+1, 0);

EDIT: I've tried sending the word 'TEST' between the two hosts without success.

FIXED: I had an ampersand in front of the message variable as I was passing it.

Should have been:

send(sock, message, strlen(message)+1, 0);
Khronos
  • 377
  • 6
  • 17

4 Answers4

2

I'm not sure if C99 provides a standard for encoding but I suppose it's implementation specific. It could be US-ASCII for example.

What happens is that a Java InputStreamReader (or output) uses the default charset specified somewhere in the OS or the Java installation (not sure where) so it may differ compared to the one used by the C program.

The best thing you can do is to test various encodings, the InputStreamReader class indeed provides a specific constructor:

public InputStreamReader(InputStream in, Charset cs)

in which you are allowed to specify which charset you want to use. Take a look here for possible charsets.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • The C client is using the US-ASCII charset according to nl_langinfo(CODESET) so it's not a character encoding issue. I have also forced the Java server to use this character set using InputStreamReader without success. – Khronos May 24 '12 at 04:46
1

You also have to look at endian disparity: Java uses network order, while the C host may not. ByteBuffer, illustrated here, may help.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
1

If I'm not wrong you have something like:

char *message = "Hello";

When you send by:

send(sock, &message, strlen(message)+1, 0);
           |
           +---- Err.

You send address of message and not the message itself, further you set the length to length of message and such padding with garbage.

If you do this instead:

send(sock, message, strlen(message)+1, 0);

It should work.

Or use char message[] = "Hello";


To further dissect server data you could do something like:

        int i = 0;
        for (char ch : inputString.toCharArray()) {
            System.out.printf("%2d: 0x%02X o%03o %3d %c%n",
                i++,
                (int)ch & 0xff,
                (int)ch & 0xff,
                (int)ch & 0xff,
                Character.isISOControl(ch) ? '.' : ch
            );
        }

or

        buf = inputLine.getBytes(/* charset  */);
        for (i = 0; i < buf.length; ++i) {

etc.

Client siad: Hello
 0: 0x00 o000   0 .
 1: 0x48 o110  72 H
 2: 0x65 o145 101 e
 3: 0x6C o154 108 l
 4: 0x6C o154 108 l
 5: 0x6F o157 111 o

Using &message:

Client said: `�
 0: 0x60 o140  96 `
 1: 0xEF o357 239 ￯
 2: 0xBF o277 191 ﾿
 3: 0xBD o275 189 ᄑ
 4: 0x04 o004   4 .
 5: 0x08 o010   8 .

Another hack/debug/thing one can do is something like:

    while (true) {
        in.mark(128);
        if ((inputLine = in.readLine()) == null)
            continue;

        System.out.println("Response: " + inputLine);

        in.reset();
        i = 0;
        while (in.ready()) {
            c = in.read();
            System.out.printf("%2d: 0x%02X o%03o %3d %c%n",
                i++,
                c, c, c,
                Character.isISOControl((char) c) ? '.' : (char)c
            );
        }
    }
Morpfh
  • 4,033
  • 18
  • 26
0

your problem looks like the byte alignment

in your C client you need to convert the host to network byte order.

use

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);
Jay D
  • 3,263
  • 4
  • 32
  • 48