日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C与java通讯小结

發布時間:2024/1/23 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C与java通讯小结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在做java和c的UDP通信,才發現自己的通信基礎知識基本為0,汗一個。。不過還好,在大家的幫助下,終于完成了。。下面寫下一些小的總結。
(1)字節序問題:這個是通訊的大問題。。前面幾篇文章也轉載了查閱到的一些資料。總的來說C一般使用的是小尾存儲數據,而java使用大尾存儲,所謂大尾存儲就是數據高字節在前,低字節在后存儲。而網絡中的數據則都是大尾存儲。另字符串在傳輸過程中不會發生變化,而int,long等數值類型的數據會經過根據大小尾進行存儲傳輸。所以當java與c進行通信的時候,java一段數據基本不用進行大小尾轉化,而c收到數據后要進行NToH轉化,發送數據的時候也要進行HToN數據轉化。再加上字符串,打成包傳輸即可。
(2)傳輸包問題:總所周知,傳輸數據不可能一個字節一個字節發送,沒有意義,當然要打成代表一定意義的包進行發送,包就要有包頭,包尾。比如下面包的定義:

消息結構

項目

說明

Message Header

消息頭(所有消息公共包頭)

Message Body

消息體

?

消息頭格式Message Header

字段名

字節數

類型

描述

Total_Length??

4

Unsigned? Integer

消息總長度(含消息頭及消息體)

Command_Id

4

Unsigned Integer

命令或響應類型

Sequence_Id

4

Unsigned Integer

消息流水號,順序累加,步長為1,循環使用(一對請求和應答消息的流水號必須相同)

Version

4

Unsigned Integer

表示,當前網站與AS核心代碼通訊的版本號。目前的版本號為:0x0002


消息體如下:

發送請求:

字段名

字節數

類型

描述

AS服務器名稱

22

Octet String

AS服務器名稱

機構名稱

22

Octet String

機構名稱

起始日期

4

Unsigned Integer

證書有效起始日期

結束日期

4

Unsigned Integer

證書有效終結日期

?

響應

字段名

字節數

類型

描述

AS服務器名稱

22

Octet String

AS服務器名稱

機構名稱

22

Octet String

機構名稱

證書路徑

128

Unsigned string

證書在本機存儲路徑

結果值

1

char

0:解析正確,1:解析錯誤

?

這樣當發送的時候需要把消息頭和消息體構建出來,并全部轉化成byte數組,再進行傳輸。
再者對數據包發送的時候,是根據接口文件的。。也就是java和c通訊接口文件,自己定義的了,一致就行。這里面如上面包格式所示,都定義好了每個字段的長度,那么當讀取的時候也要根據這個長度進行讀取。那么當實際的長度沒有這么長怎么辦呢?那就需要雙方定義好填充字符,是使用空字符('\0')呢,還是空格(' ')呢,c里面讀取一般遇到空字符就停止。所以使用空字符會比較普遍一些。當java接收到數據后,也要根據找個字符解析出真正長度的字符串。比如使用下面函數去掉后面的空字符:
??

private String getRealData(byte[] temp){String res = new String(temp);int end = res.indexOf('\0');String result = res.substring(0,end);return result;}

?

而java得到包之后,如何得到每個字段呢,這個沒有別的辦法了,只能一段一段的拷貝了。下面是我使用的拷貝方法:

private String getServerName() {byte[] temp = new byte[22];System.arraycopy(this.getRawData(), 1, temp, 0, temp.length);String encodeStr = getRealData(temp);return new String(Base64.decode(encodeStr.getBytes()));}

?

而c中則使用結構體就可以了。定義好結構體,接受的之后直接接受結構體,然后根據結構體讀取,方便快捷,java這方面確實有點麻煩了。
(3)byte,string區別:本來以為傳輸的時候就是string類型字符串,原來根本不是一回事。網絡上傳輸數據都是字節碼,就是我們常說的ascII碼的,對應到類型上就是byte類型的。而string只是java中一種對象而已。而且java中編碼一般是unicode編碼的,要進行和byte類型的轉化。int和long類型的也要進行int2byte轉化。
接收到數據之后,則要進行byte2int轉化。且值得注意的是int轉成byte并不是直接字符串的轉化,比如123轉成字符串就是123,但是轉成byte就不是了。它要根據整數123所占的字節,得到每個字節的值,再轉成byte數組。常用的轉化函數有:

//int2byte public static byte[] intToByte(int n) {byte[] b = new byte[4];b[0] = (byte) (n >> 24);b[1] = (byte) (n >> 16);b[2] = (byte) (n >> 8);b[3] = (byte) (n);return b;}public static void int2byte(int n, byte buf[], int offset) {buf[offset] = (byte) (n >> 24);buf[offset 1] = (byte) (n >> 16);buf[offset 2] = (byte) (n >> 8);buf[offset 3] = (byte) n;}// 字節類型轉成int類型public static int byte2int(byte b[]) {return b[3] & 0xff | (b[2] & 0xff) << 8 | (b[1] & 0xff) << 16| (b[0] & 0xff) << 24;} //short2byte public static byte[] short2byte(int n) {byte b[] = new byte[2];b[0] = (byte) (n >> 8);b[1] = (byte) n;return b;} // long到byte的轉換public static byte[] long2byte(long n) {byte b[] = new byte[8];b[0] = (byte) (int) (n >> 56);b[1] = (byte) (int) (n >> 48);b[2] = (byte) (int) (n >> 40);b[3] = (byte) (int) (n >> 32);b[4] = (byte) (int) (n >> 24);b[5] = (byte) (int) (n >> 16);b[6] = (byte) (int) (n >> 8);b[7] = (byte) (int) n;return b;}

?

等等,注意:這里只是進行普通的字節碼和數值之間的類型轉換,并不進行高低位轉化。原因前面已經說過了,java和網絡字符是一樣的,都是高位前,低位后,所以不用進行轉化。

(4)中文傳輸問題:
網絡中傳輸中文極易出現亂碼,那怎么辦比較好呢,對了,就是對中文進行編碼,常用的是Base64編碼。再對編碼后數據進行傳輸,接收到后也要先進行base64解碼即可。

總結

以上是生活随笔為你收集整理的C与java通讯小结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。