【问题标题】:C Structure to Java objects over UDP通过 UDP 到 Java 对象的 C 结构
【发布时间】:2011-06-29 14:18:22
【问题描述】:

我对 Java 和 C 编程都很陌生,需要一些帮助。 所以我有一个通过 UDP 发送结构的 C 应用程序:

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

}

现在我需要能够在 Java 中通过 UDP 接收这些数据并使用这些值填充对象。我可以获得第一个字符串(名称),但不确定如何获取剩余的项目。

 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 结构中。

非常感谢。

【问题讨论】:

    标签: java c serialization udp


    【解决方案1】:

    由于字节序和位打包问题,您通常不应将 C 结构写入网络。相反,您希望通过一个编组和编码过程,以可移植的网络编码格式写出每个结构内存。另一端读取可移植网络格式并根据需要存储它。

    这就是所有 Internet 标准 RFCish 协议的工作方式。它们定义了所有字段的顺序、编码、字节顺序和其他语义。是的,他们有时会安排它,以便将精心构建的结构覆盖在网络缓冲区上,但即便如此,他们也经常需要在缓冲区上执行 htons() 或朋友,以使它们进入正确的字节序。

    我建议采用这种方法。

    阅读您的结构,它不是以促进直接在网络上发送的方式布置的。例如,结构中似乎很可能存在漏洞,其他系统很难正确解码。

    【讨论】:

    • 这听起来像是一个明智的长期解决方案。为了跨语言友好,推荐的方法是什么?我应该走谷歌的协议缓冲区路线吗?结构相当简单,不必更改。这也需要在运行时快速。如果您能指出正确的方向,将不胜感激。
    • @Andrey:对于一个中等大小的结构,我只是手动完成。 write(fd,b.name,sizeof(b.name)); tmpushort = htons(b.did); write(fd,tmpushort,sizeof(tmpushort)); tmpuchar = b.type; write(fd,tmpuchar,sizeof(tmpuchar)); tmpuint=htonl(b.window); write(fd,tmpuint,sizeof(tmpuint)); 等。如果您使用u_int8_tu_int16_tu_int32_t 来减轻您在各种平台上对 char/short/int/long 大小的依赖,则可以加分。另一方面,将其读入,从网络顺序转换回主机顺序,然后根据需要存储它。
    【解决方案2】:

    一种方法是从 byte[] 数据创建 java.io.ByteArrayInputStream,并将其包装在 DataInputStream 中,它提供读取其他原始类型的方法。

    您可能希望按网络字节顺序传递整数。在 C 端,你可以使用 ntohl、htonl、ntohs、htons 等。如果你使用位域,你将不得不在 Java 端手动翻译它们。

    【讨论】:

      【解决方案3】:

      很多人已经为这个问题提供了很好的答案。只是通过 UDP 数据报发送一个 c 结构很可能会随着时间的推移而导致问题。使用 XML 或 JSON 进行序列化将为您提供更大的灵活性和发送方/接收方的独立性。

      话虽如此...Java 有一种简单的方法来做你想做的事。只需使用 ByteBuffer 包装入站 UDP 数据报中的字节数组。 ByteBuffer 具有从 ByteBuffer 获取字节、字符(Java 字符,如 Unicode 字符)、short、int 和 long 的方法。

      代码很简单。然而,正如其他人所指出的......这仍然是一个坏主意。如果可能,请使用 JSON 或 XML。将 JSON 或 XML 以 UTF-8 格式存储在 UDP 数据报中,然后再发送。在接收端,将 UTF-8 转换回 Java 字符串(包含 UTF-8 的字节数组上的 new String() 可以正常工作),然后解组 JSON 或 XML。

      【讨论】:

        【解决方案4】:

        你需要先序列化你的数据,然后在java中解码。

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

        当然,您可以使用真实的RPC technology

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多