跨语言之间的socket通信(C--Java的握手)

这些日子在公司开发一个基于B/S的服务器监控的, 服务器端是视频电话系统,是C语言UDP的WinSock建立的Socket监听,客户端我是用了JSP进行开发,开发环境是MyEclipse6.0+Tomcat5.5+jdk6.0,于是要用Java的UDP socket与WinSock进行握手谈话,嘻嘻,说得形象了点。首先开始谈话吧!!!!!!!!.................

(1)谈话开始,先讲下一点网络知识吧。

xuanner老师:socket握手后,双方通信的是什么东西呢?

学生:就是字节。

xuanner老师:那是什么字节?主机字节还是网络字节?

学生:网络字节。

xuanner老师:那解释下网络字节跟主机字节有什么区别?

学生:想了想说,就是高位在前跟在后的区别了,网络字节是高位在前,低位在后的,而主机字节是低位在前,高位在后。比如说在C语言声明一个int类型的值,它是四个字节保存的,它的前两个字节就是高位,后两个字节就是低位,有一种算法可以把它转为网络字节。(后面提供)

xuanner老师:好,不错!!那么 WinSock握手后发数据包时,Java Socket取得到后如何处理呢?

学生:得到数据包(字节数组)后,再把网络字节转为主机字节就可以了,有一种算法可以把它转为主机字节。(后面提供)

xuanner老师:对,还挺聪明的。但如果WinSock握手后发送的数据包含有字符呢,或是中文字符呢?该如何实现呢?

学生:想了又想,不知道怎么回答。回答不会。

xuanner老师:首先要了解C语言与Java语言数据类型的数据编码与存储格式,C语言字符是以系统默认GBK为编码格式,而Java语言字符是以JVM为编码格式。WinSock发送数据包是字符以ANSI存储格式发送的,到了Java Socket后,直接将其转换为String类型。

xuanner老师:那如果是Java Socket发送的数据包含有中文字符,如何打包?

学生:直接把String以GBK编码格式转换为bytes即可。

 因为现行的计算机都是以八位一个字节为存储单位,那么一个16位的整数,也就是C语言中的short,在内存中可能有两种存储顺序big-endian和litte-endian.考虑一个short整数0x3132(0x32是低位,0x31是高位),把它赋值给一个short变量,那么它在内存中的存储可能有如下两种情况:

大端字节(Big-endian):

----------------->>>>>>>>内存地址增大方向

short变量地址

       0x1000                  0x1001

_____________________________

|                           |

|         0x31             |       0x32

|________________ | ________________

高位字节在低位字节的前面,也就是高位在内存地址低的一端.可以这样记住(大端->高位->在前->正常的逻辑顺序)

 

小端字节(little-endian):

----------------->>>>>>>>内存地址增大方向

short变量地址

       0x1000                  0x1001

_____________________________

|                           |

|         0x32             |       0x31

|________________ | ________________

低位字节在高位字节的前面,也就是低位在内存地址低的一端.可以这样记住(小端->低位->在前->与正常逻辑顺序相反)

 

好啦,网络socket握手讲解完毕。

(2)数据类型编码算法

<1>Java 中int类型主机字节转换为网络字节算法[ 封包 ]

/** *//** 

  * 将int转为低字节在前,高字节在后的byte数组

  */

 // 封包int算法

private static byte[] InttoByteArray(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;

}

<2>Java中short类型主机字节转换为网络字节算法[ 封包 ]

/** *//**

  * 将short转为低字节在前,高字节在后的byte数组(网络字节)

  */

//封包short算法

private static byte[] ShorttoByteArray(short n) ...{

        byte[] b = new byte[2];

        b[1] = (byte) (n & 0xff);

        b[0] = (byte) (n >> 8 & 0xff);        

        return b;

}

<3>Java 中int类型网络字节转换为主机字节算法[ 解包 ]

// 解包为int算法

private static int ByteArraytoInt(byte[] b) ...{

        int iOutcome = 0;

        byte bLoop;

        for (int i = 0; i < 4; i++) ...{

                bLoop = b[i];

                iOutcome += (bLoop & 0xff) << (8 * i);

        }

        return iOutcome;

}

<4>Java 中short类型网络字节转换为主机字节算法[ 解包 ]

// 解包为short算法

privatestatic short ByteArraytoShort(byte[] b) ...{

        short iOutcome = 0;

        byte bLoop;

        for (int i = 0; i < 2; i++) ...{

                bLoop = b[i];

                iOutcome += (bLoop & 0xff) << (8 * i);

        }

        return iOutcome;

}

<5>Java中ANSI字符数组转为String字符串[ 解包 ]

// 解包为String算法

private static String ByteArraytoString(byte[] b) ...{

        // 转化为Unicode编码格式

        String retStr = "";

        try ...{

                retStr = new String(b, "GBK");         //"GB2312"也可以

        } catch (Exception e) ...{

        }

        return retStr.trim();

}

<6>Java中String字符串转换为ANSI字符数组[ 封包 ]

public byte[] StringtoByteArray(String str) ...{

        byte[] retBytes = null;

        try ...{

                retBytes = str.getBytes("GBK");         //"GB2312"也可以

        } catch(Exception ex) ...{}

        return retBytes;

}

       总结:解决java的字符编码问题首先需要明确的是你的问题中涉及到哪些编码,当前默认编码(不一定是系统的,而是JVM的)是什么,然后才好利用各种解决方法来解决。


原文来自于狗粮网:http://www.taotuike.cn

你可能感兴趣的:(跨语言之间的socket通信(C--Java的握手))