Структура C для объектов Java через UDP - PullRequest
4 голосов
/ 29 июня 2011

Я довольно новичок в программировании на Java и C, и мне нужна помощь.Итак, у меня есть приложение C, которое отправляет структуры по 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));

}

Теперь мне нужно иметь возможность получать эти данные по UDP в Java и заполнять объект этими значениями.Я могу получить первую строку (имя), но не знаю, как поступить с оставшимися элементами.

 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);
    }
  }
}

Я посмотрел на буферы протокола Google, но, очевидно, он требует изменений с обеих сторон.Мне также нужно иметь возможность в конечном итоге отправить эти данные из Java-объекта в UDP и обратно в C-структуру.

Большое спасибо.

Ответы [ 4 ]

3 голосов
/ 29 июня 2011

В общем случае не следует записывать структуры C в сеть из-за проблем с порядком байтов и порядком битов.Вместо этого вы хотите пройти через процесс маршаллинга и кодирования, где вы записываете каждую структуру памяти в формате переносимого сетевого кодирования.Другая сторона читает данные в формате переносимой сети и сохраняет их по мере необходимости.

Так работают все стандартные интернет-протоколы RFCish.Они определяют порядок, кодировки, порядковый номер и другую семантику всех полей.Да, они иногда организуют это так, что тщательно скомпонованная структура может быть наложена на сетевой буфер, но даже тогда им часто нужно выполнять htons () или друзей в буферах, чтобы получить их в правильном порядке байтов.1004 * Я рекомендую использовать этот подход.

Читая вашу структуру, она не выложена таким образом, который способствует отправке прямо в сеть.Например, очень вероятно, что в структуре есть дыры, которые другим системам было бы очень трудно правильно декодировать.

1 голос
/ 29 июня 2011

Один из способов - создать из данных byte [] файл java.io.ByteArrayInputStream и обернуть его в DataInputStream, который предлагает методы для чтения других примитивных типов.

Возможно, вы захотите передавать целые числа в порядке сетевых байтов. На стороне C вы можете использовать ntohl, htonl, ntohs, htons и т. Д. Если вы используете битовые поля, вам придется переводить их вручную на стороне Java.

0 голосов
/ 27 ноября 2013

Несколько человек уже дали неплохие ответы на этот вопрос.Простая отправка структуры через UDP-дейтаграмму может со временем вызвать проблемы.Сериализация с использованием XML или JSON даст вам большую гибкость и независимость от отправителя / получателя.

Как уже было сказано ... У Java есть тривиальный способ сделать то, что вы хотите.Просто оберните байтовый массив из входящей UDP-дейтаграммы, используя ByteBuffer.ByteBuffer имеет методы для получения байтов, символов (Java-символов, как в Unicode-символах), шортов, целых и длинных значений из ByteBuffer.

Код очень прост.Однако, как уже отмечали другие ... Это все еще плохая идея.Используйте JSON или XML, если возможно.Сохраните JSON или XML в формате UTF-8 в дейтаграмме UDP перед отправкой.На принимающей стороне преобразуйте UTF-8 обратно в строку Java (новая String () в байтовом массиве, содержащем UTF-8, работает должным образом), а затем отмените маршализацию JSON или XML.

0 голосов
/ 29 июня 2011

Вам необходимо сначала сериализовать данные, а затем декодировать их в Java.

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

Конечно, вы можете использовать настоящую RPC-технологию .

...