Link to home
Start Free TrialLog in
Avatar of pfgrobler
pfgrobler

asked on

Read a c STRUCT from a socket connection


I have a existing  application that consists of several proceses that cumunicate with each other using TCP/IP sockets. The application runs on HP-UX and was written in c.

I want to redevelop one of the processes in Java. The process must be able to read the c struct from the socket and write back return messages aswell.

the struct i sdefined as

#define EVENT_MESSAGE struct event_message_struct
EVENT_MESSAGE {
     char id[8];
     char event_code[4];
     char request_handle[12];
     char filename[40];
};

I can connect to the socket
but using a DataInputstream and readline() results in carbage.

SOLUTION
Avatar of girionis
girionis
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
 Also note that a character in Java is 16 bits while in C it is 8...
Avatar of lwinkenb
lwinkenb

Try sending string representations of the data that is in the struct.  Then if you read them on the java side using a BufferedReader, you dont have to worry about the 16 bit vs 8 bit thing.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Or, better:

int id = dis.readInt();
char event_code = dis.readChar();
dis.read(request_handle);
String _filename = new String(dis.read(filename));
...and yet another improvement ;-)

int event_code = dis.readUnsignedShort();
CEHJ, are you sure about the byte order? Java definitely uses small-endian, but I personally don't know HP-UX byte order. If it's different, your initial variant with arrays might be better.
I would think it should be OK. Applications pushing out data over sockets should use network byte order (little-endian)
If structure is defined as in the intitial post, bytes won't be reordered--fields declared as byte arrays, not multibyte integers. The question remains whether that fields mean multibyte integers. What applications are pushing, IMO often depends on developer expectations and lazyness. If it is known that other end will run on the same platform, byte ordering qustion may seem non-issue. Until someone forgets initial assumption and tries to start inter-platform communication.
Well - the ordering should be apparent pretty soon ;-)
Avatar of pfgrobler

ASKER

I have some sucsess  the datatype was CHAr and not byte .
But using :

    char[] id = new char[8];
    char[] event_code = new char[4];
    char[] request_handle = new char[12];
    char[] filename = new char[40];


   System.out.println("START");
   System.out.println(d.read(id)  + " : " + String.valueOf(id));
   System.out.println(d.read(event_code) + " : " + String.valueOf(event_code) );
   System.out.println(d.read(request_handle)+ " : " + String.valueOf(request_handle) );
   System.out.println(d.read(filename)+ " : " + String.valueOf(filename) );

The result that I get is :
8 : GMD
4 : 00  
12 : 760952@
40 : 00760952.msgè@`+ è@

id and eventcode is fine but request_handle and  filename includes some garbage at the end. I asume that is because the data is shorter than the actual space allocated to it . How can I insure only the relavant data is read ?
Note that java char is 2-byte, while C char is one byte. You have to read bytes. It seems that your char arrays get implicitly casted to byte arrays--there are no methods accepting char arrays in DataInputStream. Garbage at the end caused by not interpreting \0 as terminator--java straings can have embedded \0.
Yes, read it into byte arrays. The handle field is numeric is it not? For the filename, i'd use a similar approach to the following:

            byte[] filename = { 'a', 'b', 'c', '\0', '\1', '\2', '\3' };
            boolean zeroOut = false;
            for(int i = 0;i < filename.length;i++) {
                  if (filename[i] == '\0') {
                        zeroOut = true;
                  }
                  if (zeroOut) {
                        filename[i] = 0;
                  }
            }
            System.out.println(new String(filename));