CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

在线等待:: java与C语言socket通讯,C语言的结构体我怎么接收? up有分

楼主xhjf777(古格国王)2005-04-29 16:00:14 在 Java / J2SE / 基础类 提问

如题,   我要和C语言程序作socket通讯,但C语言程序中的socket发送接收都用了结构体,而java中没有结构体的概念,我该怎么作?   为每一个C结构体写一个对应的类?   那我的类怎么接收它的结构体呢?  
   
  谁给举个例子呀  
   
  多谢了,   在线等待.. 问题点数:50、回复次数:10Top

1 楼steedhorse(晨星)回复于 2005-04-29 16:09:44 得分 40

哪有直接用Java接收结构体的。  
  通信协议必须明确规范每一个字段的类型、长度、字节顺序等信息,直接发结构体,那么除非两边都使用C语言编程,而且使用同样类型的CPU,使用同样的编译器编译,而且使用同样的编译选项。Top

2 楼xhjf777(古格国王)回复于 2005-04-29 16:18:06 得分 0

to   steedhorse(晨星):  
          但是对方的c程序就是发送一个结构体数据过来,我现在的问题就是怎么接收它呢?  
          我把数据全部接收过来后,然后取前多少字节作为一个东西,再取从某个位置到某个位置的若干字节作为另外一个东西,但是不同的机器和操作系统上相同数据类型也未必占用相同的字节,我这样作也会存在问题吧?  
   
          我该怎么作呢?Top

3 楼HitXU(一天不学习,赶不上刘少奇)回复于 2005-04-29 16:25:54 得分 10

转贴::  
   
  近几天看到csdn上问c/c++和java通信的问题比较多,特别是c特有的数据结构(如struct)。  
   
  特地根据网友的一个问题举个例子,希望对初学者有所帮助。  
   
  原问题见:http://community.csdn.net/Expert/topic/3886/3886989.xml?temp=.3527033  
   
  这类问题通常是为了利用原有Server或者Server不能做修改(通常是c/c++)造成。  
   
  比如Server端只接收一个结构Employee,定义如下:  
   
  struct   UserInfo   {  
      char   UserName[20];  
      int   UserId;  
  };  
  struct   Employee   {  
      UserInfo   user;  
      float   salary;  
  };  
  当然也可以定义为  
   
  struct   Employee   {  
      char   name[20];  
      int         id;  
      float   salary;  
  };  
   
   
  java   client   测试源码(为说明问题,假设struct字节对齐,sizeof(Employee)=28)  
   
  import   java.net.*;  
   
  /**  
    *   与C语言通信(java做Client,c/c++做Server,传送一个结构)  
    *   @author   kingfish  
    *   @version   1.0  
    */  
  class   Employee   {  
      private   byte[]   buf   =   new   byte[28];     //为说明问题,定死大小,事件中可以灵活处理  
   
      /**  
        *   将int转为低字节在前,高字节在后的byte数组  
        */  
      private   static   byte[]   toLH(int   n)   {  
          byte[]   b   =   new   byte[4];  
          b[0]   =   (byte)   (n   &   0xff);  
          b[1]   =   (byte)   (n   >>   8   &   0xff);  
          b[2]   =   (byte)   (n   >>   16   &   0xff);  
          b[3]   =   (byte)   (n   >>   24   &   0xff);  
          return   b;  
      }  
   
      /**  
        *   将float转为低字节在前,高字节在后的byte数组  
        */  
      private   static   byte[]   toLH(float   f)   {  
          return   toLH(Float.floatToRawIntBits(f));  
      }  
   
      /**  
        *   构造并转换  
        */  
      public   Employee(String   name,   int   id,   float   salary)   {  
          byte[]   temp   =   name.getBytes();  
          System.arraycopy(temp,   0,   buf,   0,   temp.length);  
   
          temp   =   toLH(id);  
          System.arraycopy(temp,   0,   buf,   20,   temp.length);  
   
          temp   =   toLH(salary);  
          System.arraycopy(temp,   0,   buf,   24,   temp.length);  
      }  
   
      /**  
        *   返回要发送的数组  
        */  
      public   byte[]   getBuf()   {  
          return   buf;  
      }  
   
      /**  
        *   发送测试  
        */  
      public   static   void   main(String[]   args)   {  
          try   {  
              Socket   sock   =   new   Socket("127.0.0.1",   8888);  
              sock.getOutputStream().write(new   Employee("kingfish",   123456789,   8888.99f).  
                                                                        getBuf());  
              sock.close();  
          }  
          catch   (Exception   e)   {  
              e.printStackTrace();  
          }  
   
  }   //end  
   
  ---------------------------------------------------------------------------  
   
  当然,也可以利用writeInt,writeFloat方法发送,但字节顺序需要改为低在前。  
  这个问题稍后在讨论。  
   
   
  如有任何问题,请指正!  
   
  kingfish  
  2005.3.29  
   
  Top

4 楼HitXU(一天不学习,赶不上刘少奇)回复于 2005-04-29 16:26:19 得分 0

本部分提出另外一种做法,   供参考。  
   
   
  import   java.net.*;  
  import   java.io.*;  
   
  /**  
    *   与C语言通信(java做Client,c/c++做Server,传送一个结构)  
    *   @author   kingfish  
    *   @version   1.0  
    */  
  public   class   Employee2   {  
      private   String   name;  
      private   int   id;  
      private   float   salary;  
   
      /**  
        *   将int转为低字节在前,高字节在后的int  
        */  
      private   static   int   toLH(int   in)   {  
          int   out   =   0;  
          out   =   (in   &   0xff)   <<   24;  
          out   |=   (in   &   0xff00)   <<   8;  
          out   |=   (in   &   0xff0000)   >>   8;  
          out   |=   (in   &   0xff000000)   >>   24;  
          return   out;  
      }  
   
      /**  
        *   将float转为低字节在前,高字节在后的int  
        */  
      private   static   int   toLH(float   f)   {  
          return   toLH(Float.floatToRawIntBits(f));  
      }  
   
      /**  
        *   构造并转换  
        */  
      public   Employee2(String   name,   int   id,   float   salary)   {  
          this.name   =   name;  
          this.id   =   id;  
          this.salary   =   salary;  
      }  
   
      /**  
        *   取得名字,定长byte数组  
        */  
      public   byte[]   getName()   {  
          byte[]   b   =   new   byte[20];  
          System.arraycopy(name.getBytes(),   0,   b,   0,   name.getBytes().length);  
          return   b;  
      }  
   
      /**  
        *   取得编号(低字节在前)  
        */  
      public   int   getId()   {  
          return   toLH(id);  
      }  
   
      /**  
        *   取得工资(低字节在前)  
        */  
      public   int   getSalary()   {  
          return   toLH(salary);  
      }  
   
      /**  
        *   发送测试  
        */  
      public   static   void   main(String[]   args)   {  
          try   {  
              Employee2   p   =   new   Employee2("kingfish",   123456789,   8888.99f);  
   
              Socket   sock   =   new   Socket("127.0.0.1",   8888);  
              DataOutputStream   dos   =   new   DataOutputStream(sock.getOutputStream());  
              dos.write(p.getName());  
              dos.writeInt(p.getId());  
              dos.writeInt(p.getSalary());  
              sock.close();  
          }  
          catch   (Exception   e)   {  
              e.printStackTrace();  
          }  
      }  
  }   //end  
   
  -----------------------------------------------------------------------------------------------------  
   
  如有任何问题,请指正!  
   
  kingfish  
  2005.3.30  
   
  Top

5 楼steedhorse(晨星)回复于 2005-04-29 16:32:16 得分 0

那你要明确两件事:  
  (1)对于多字节类型,比如int,它那边的CPU是高字节在前还是低字节在前,现在Intel   X86系列的CPU用得多,一般是低字节在前。但如果他转换过了,那么可能就是高字节在前。  
  (2)他编译时是否按俺默认的结构体字对齐还是重新设过pack选项,如果是默认的,那么通常是按照4字节对齐,比如有个char[21]字段,后面跟一个int,那么取出21个字节的字符串之后,应该跳过3个字节取int。当然,如果它设置了pack(1),没有字节对齐,最好。Top

6 楼steedhorse(晨星)回复于 2005-04-29 16:34:20 得分 0

唉,真有些人不负责,编写网络通信程序,不管使用什么语言,都不能简单地假设通信对方也用C/C++,也用X86系列的CPU啊。Top

7 楼xhjf777(古格国王)回复于 2005-04-29 20:15:17 得分 0

to   steedhorse(晨星),  
          是啊,所以我的疑问就是这样弄有太多的写死的情况,遇到某些机器和系统就得改程序,显然这样的程序是一个很失败的程序.  
   
          真的找不到一个好的解决方法了吗?Top

8 楼steedhorse(晨星)回复于 2005-04-29 20:24:08 得分 0

不过实际可能没那么糟糕,因为:  
  (1)实际中使用的可能还是Intel   X86系列的CPU多一些,所以基本上可以按照低字节在前统一处理;  
  (2)如果原来程序的作者不太服责,那么说不定他根本没改过编译器的默认编译选项,就是采用默认的4字节对齐,也可以统一处理。  
  (3)也说不定你们的结构体里面没有需要填充的区域,比如没有char[M]后面接一个int字段的情况,而M不是4的整数倍,也没有连续奇数个short然后接着一个int的情况。  
   
  当然,还有一种可能,那就是原来程序的作者还是比较负责的,他已经采用编译选项取消了字对齐,而且采用字节顺序转换函数把所有的多字节字段都转换成了网络传输中通用的高字节在前的顺序,那样就更好了。Top

9 楼jack286(jack286)回复于 2005-07-18 21:33:19 得分 0

严重关注Top

10 楼jack286(jack286)回复于 2005-07-18 22:14:15 得分 0

大哥,你给的程序执行有错误啊Connection   refused:   connect  
  Top

相关问题

  • java 与c++用socket通讯的问题??字符串不能接收到??急啊!
  • java中要接收C的结构体,怎么办?
  • C# 线程问题,socket接收到数据后,分不够再加
  • C#里的Socket的同步接收怎么Receive怎么设置超时?
  • 110分:JAVA中Socket如何发送和接收字节数组?
  • socket接收问题
  • java和C Socket通信问题!!
  • C和Java的Socket通信问题
  • 关于 Socket, C# 和 JAVA 通信
  • java与c/c++

关键词

  • .net
  • c/c++
  • 结构
  • 语言
  • 字段
  • cpu
  • 编译
  • 选项
  • 通信
  • 转换

得分解答快速导航

  • 帖主:xhjf777
  • steedhorse
  • HitXU

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo