zoukankan      html  css  js  c++  java
  • Java与C++Socket通讯注意事项

    c++与java进行socket通信时注意事项

    原文链接: http://my.oschina.net/ypimgt/blog/106439

        因为java发送的都是网络字节序(big-endium),而c++是主机字节序(little-endium),所以当消息中有整型,浮点型(应尽量避免使用)的时候需要用htonl,htons,ntohl,ntohs等函数转换一下,字符串由于是单字节排序的不需要转换,但应注意c++字符串是以'/0'作为结束符的,如果找不到'/0'可能会出现一些乱码,所以接收的时候可以分配一个length+1的buffer用来接收消息. 


    举例:c++ server, java client,假设开发的是c++ server,那么: 


    java client--------->c++ server: c++ server需要调用ntohs,ntohl 
    c++ server--------->java client: c++ server需要调用htons,htonl 


    至于浮点型可以使用以下的函数转换: 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    float tcp_htonf(float f)
    {
     unsigned char *p, p0, p1;
     if(htons(1) ==1) return f;
     p =(unsigned char *)&f;
     p0 =p[0];
     p1 =p[1];
     p[0] =p[3];
     p[3] =p0;
     p[1] =p[2];
     p[2] =p1;
     return f;
    }
     
    float tcp_ntohf(float f)
    {
     unsigned char *p, p0, p1;
     if(ntohs(1) ==1) return f;
     p =(unsigned char *)&f;
     p0 =p[0];
     p1 =p[1];
     p[0] =p[3];
     p[3] =p0;
     p[1] =p[2];
     p[2] =p1;
     return f;
    }



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    double tcp_htond(double d) 
     unsigned char *p, p0, p1, p2, p3;   
     if(htons(1) ==1) return d; 
     p =(unsigned char *)&d; 
     p0 =p[0]; 
     p1 =p[1]; 
     p2 =p[2]; 
     p3 =p[3];
     p[0] =p[7]; 
     p[7] =p0; 
     p[1] =p[6]; 
     p[6] =p1;?? 
     p[2] =p[5];?? 
     p[5] =p2;
     p[3] =p[4]; 
     p[4] =p3; 
     return d; 



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    double tcp_ntohd(double d) 
    {
     unsigned char *p, p0, p1, p2, p3;
     if(ntohs(1) ==1) return d;   
     p =(unsigned char *)&d;
     p0 =p[0]; 
     p1 =p[1]; 
     p2 =p[2]; 
     p3 =p[3]; 
     p[0] =p[7]; 
     p[7] =p0; 
     p[1] =p[6]; 
     p[6] =p1; 
     p[2] =p[5];
     p[5] =p2;
     p[3] =p[4];
     p[4] =p3;
     return d; 
    }





    java代码发送结构体 
    最近给个朋友做个网站的客户端,使用C/S模式,Client为VC6开发,Server为Java,通过Socket通信。由于Client这边为C++,所以,在接受Java发过来的数据包时,需要知道发来的包的长度,所以,就要引入变长包的机制。 
    方法是:首先Server发送一个包头,如下: 
    // packet head 
    typedef struct tagPacketHead{ 
    long PacketID; 
    long PacketLen; 
    }PacketHead; 
    包头后面跟上包体,其中包体的长度,就是上面结构体中的PacketLen,Clinet首先接受包头,因为包头是两边约定好的,所以可以直接Receive一个定长的消息,也就是这个包头的长度的消息,从包头中取得包体的长度后,就可以再次Receive一个包体长度的消息了。那么Java中如何发送一个结构体呢?下面是解决方法: 


    package org.charry.org; 
    import java.net.*; 
    /** 

    * 字节转换,参考网络文章   
    */ 
    class Packet { 
    private byte[] buf = null; 
    /** 
    * 将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 Packet(int packetID, int packetLen, String packetBody) { 
    byte[] temp = null; 
    buf = new byte[packetBody.getBytes().length + 8]; 
    temp = toLH(packetID); 
    System.arraycopy(temp, 0, buf, 0, temp.length); 
    temp = toLH(packetLen); 
    System.arraycopy(temp, 0, buf, 4, temp.length); 
    System.arraycopy(packetBody.getBytes(), 0, buf, 8,packetBody.length()); 

    /** 
    * 返回要发送的数组 
    */ 
    public byte[] getBuf() { 
    return buf; 

    /** 
    * 发送测试 
    */ 
    public static void main(String[] args) { 
    try { 
    String tmp = “test string!”; 
    Socket sock = new Socket(”127.0.0.1″, 8888); 
    sock.getOutputStream().write( 
    new Packet(123, tmp.length(), tmp).getBuf()); 
    sock.close(); 
    } catch (Exception e) { 
    e.printStackTrace(); 



    从Client端发到Server的数据就无须特殊处理了,Java的流可以很好的处理这些。

  • 相关阅读:
    关于迭代器模式的个人理解
    设计模式之迭代器模式详解(foreach的精髓)
    关于备忘录模式的个人理解
    设计模式之备忘录模式详解(都市异能版)
    关于桥接模式的个人理解
    桥接模式详解(都市异能版)
    设计模式之 中介者模式
    关于命令模式个人的理解 撤销 重做的实现
    剑指offer 连续子数组的最大和
    剑指offer 删除链表中重复的结点
  • 原文地址:https://www.cnblogs.com/huhu0013/p/4736759.html
Copyright © 2011-2022 走看看