简体   繁体   中英

C Structure to Java objects over UDP

I am fairly new to programming in both Java and C and need some help. So I have a C application that sends out structures over UDP:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char**argv)
{
   int sockfd,n;
   struct sockaddr_in servaddr,cliaddr;

struct dataType {
    char name[4];
    unsigned short did;
    unsigned short sid;
    unsigned short type:4,pri:2,cb:2,flags:8;
    unsigned char pblock;
    unsigned char tblock;
    unsigned short mess;
    unsigned int window:24;
};

struct dataType sample_header;
strcpy(sample_header.name,"TEST");
sample_header.did=23;
sample_header.sid_id=1;
sample_header.type=1;
sample_header.pri=01;
sample_header.cb=1;
sample_header.flags=18;
sample_header.pblock=10;
sample_header.tblock=20;
sample_header.mess3;
sample_header.window=123890;

sockfd=socket(AF_INET,SOCK_DGRAM,0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
servaddr.sin_port=htons(6120);
sendto(sockfd, (char *)&sample_header, (sizeof(struct dataType)),0,(struct sockaddr *)&servaddr,sizeof(servaddr));

}

Now I need to be able to receive this data over UDP in Java and populate an object with these values. I can get the first string (name) but not sure how to go about getting the remaining items.

 import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.nio.*;

public class UDPReceive {
  public static void main(String args[]) {
    try {
      int port = 6120;

      DatagramSocket dsocket = new DatagramSocket(port);
      byte[] buffer = new byte[1024];
      DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
      while (true) {
        dsocket.receive(packet);
        byte[] data = packet.getData();
        String msg1 = new String(data, 0, 5);
        System.out.println("Here is SOME :" + msg1);
        packet.setLength(buffer.length);
      }
    } catch (Exception e) {
      System.err.println(e);
    }
  }
}

I had a look at Google's protocol buffers but it obviously requires change on both sides. I also need to be able to eventually send out this data from Java object to UDP and back into C structure.

Many Thanks.

You should not in general write out C structures to the network due to endian and bit packing issues. Instead you want to go through a marshalling and encoding process where you write out each structure memory in a portable network encoding format. The other side reads in the portable network format and stores it however it needs to.

This is how all Internet standard RFCish protocols work. They define order, encodings, endianness, and other semantics of all of the fields. Yes, they sometimes arrange it so that a carefully constructed structure can be overlaid on the network buffer, but even then they often need to perform htons() or friends on the buffers to get them into the correct endian-ness.

I recommend taking this approach.

Reading your structure, it is not laid out in a manner which promotes being sent directly on the network. It would seem very likely that there are holes in the structure, for example, which would be very difficult for other systems to decode properly.

One way is to create from the byte[] data a java.io.ByteArrayInputStream, and wrap that in a DataInputStream, which offers methods to read other primitive types.

You'll probably want to communicate integers in network byte order. On the C side, you can use ntohl, htonl, ntohs, htons, etc. If you use bit fields, you're going to have to translate them by hand on the Java side.

Several people have already provided quite good answers to this question. Just sending a c struct via a UDP datagram is likely to cause problems over time. Serialization using XML or JSON will give you much more flexibility and sender/receiver independence.

That having been said... Java has a trivial way to do just what you want. Just wrap the byte array from the inbound UDP datagram using a ByteBuffer. ByteBuffer has methods for getting bytes, chars (Java chars as in Unicode chars), shorts, ints, and longs from a ByteBuffer.

The code is very easy. However, as others have pointed out... It's still a bad idea. Use JSON or XML if you possibly can. Store the JSON or XML in UTF-8 format in the UDP datagram before sending it. On the receiving end, convert the UTF-8 back to a Java String (new String() on a byte array containing UTF-8 works properly) and then unmarshall the JSON or XML.

You need to serialise your data first and then decode it in the java.

void write_dataType( char* buff, dataType* data )
   {
   sprintf( buff, "%s\n%d\n", name, data.did );
   }

You could, of course, use a real RPC technology .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM