C言語とJava間の通信について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
jpex

C言語とJava間の通信について

#1

投稿記事 by jpex » 13年前

こちらの掲示板はいつも読ませていただいております。
書き込みはしないため、何かありましたらいってください。

現在サーバーをJava、クライアントをC,C++(DXライブラリを使用)で簡単なチャットソフトを作っているのですが、
通信データについてわからない点がありましたため、アドバイスなどいただけるとうれしいです。

C言語同士の場合、構造体をchar配列にし、先頭4バイトに命令文をつけて送受信していました。
Javaの場合、この構造体がそのまま利用できないため、テキストデータでのやり取りを行いました。

messageType,userName,chatString\n

このままでもよいのですが、直接バイナリデータなどで上記のようなやり取りはできませんでしょうか?
理想としては、C側はC同士の通信と同様に構造体をサーバーへ送信し、Javaは以下のような方法でそれを解析できるようになれば・・・と。

■クライアント側

コード:

#define HEADER_SIZE 4

struct ChatString {
[tab=30]char userName[16];
[tab=30]char chatString[64];
};

ChatString data;
strcpy_s(data.userName, sizeof(data.userName), "TEST");
strcpy_s(data.chatString, sizeof(data.chatString), "Hello World");

// 渡したデータの先頭にメッセージタイプをつけてサーバーへ送る関数
// 先頭に付与する以外はDxLibのNetWorkSendと同様です。
MySend(NetworkHandle, 10, (char *)&data, HEADER_SIZE +  sizeof(data));
■サーバー側

コード:

// byteには受信したデータが入っています。
String messageType = new String(bytes, 0, 4, "Shift_JIS");
String userName = new String(bytes, 4, 16, "Shift_JIS");
String chatString= new String(bytes, 16, 64, "Shift_JIS");
長くなってしまいましたが、よろしくお願いいたします。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C言語とJava間の通信について

#2

投稿記事 by beatle » 13年前

jpexさんが示した最後の3行のコードでは,何か問題があるのでしょうか.

jpex

Re: C言語とJava間の通信について

#3

投稿記事 by jpex » 13年前

返信ありがとうございます。
正常に動作しない内容について触れていませんでした。すみません。
また不足している点なのですが、上げさせていただいたサンプル(構造体のメンバ変数がchar)にかんしては正常に動作しました。
※chatStringにbyteからデータを取ってくる箇所のoffsetの値が20でした。

このメンバ変数がintの場合、以下の様な不具合が発生しています。

■Client / C言語 側

コード:

#define HEADER_SIZE 4
 
struct IntDataStruct {
int data1;
int data2;
};
 
IntDataStruct data;
data.data1 = 10;
data.data2 = 20;
 
// 渡したデータの先頭にメッセージタイプをつけてサーバーへ送る関数
// 先頭に付与する以外はDxLibのNetWorkSendと同様です。
// MySend(NetWorkHandle, ヘッダー, データ, 合計送信サイズ)
MySend(NetworkHandle, 35, (char *)&data, HEADER_SIZE +  sizeof(data));
■Server / Java

コード:

HexDumpEncoder hex = new HexDumpEncoder();
System.out.println(hex.encode(bytes) + " / " + bytes.length);
System.out.println("header:" + new String(bytes, 0, 4, "Shift_JIS"));
System.out.println("data1:" + new String(bytes, 4, 4, "Shift_JIS"));
System.out.println("data2:" + new String(bytes, 8, 4, "Shift_JIS"));
//実際に受信したデータ
0000: 33 35 00 00 0F 00 00 00 19 00 00 00

// 上記コードを走らせた結果
header:35
data1:□(文字化けしている)
data2:□(文字化けしている)

これはもしかして、int型のデータ(4bytes)をStringでキャストしている箇所に問題があるのでしょうか?
(char []のメンバ変数だと正常に表示されるため)
その場合、正常にint(Integer)にキャストする方法はありますでしょうか。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C言語とJava間の通信について

#4

投稿記事 by beatle » 13年前

バイト配列をStringに渡すと、それは文字データの配列として認識されます。
C言語で言えば、int変数へのポインタをchar変数へのポインタだと思ってputsで表示しようとするようなものです。

コード:

int i = 100;
puts( (char *) &i );
解決策ですが、byte配列を1バイトずつビットシフトしてint型変数に格納するとかどうでしょうか。

jpex

Re: C言語とJava間の通信について

#5

投稿記事 by jpex » 13年前

回答ありがとうございます。
教えていただいてばかりで本当に申し訳ないのですが、
int型変数へbyte配列からビットシフトして格納するにはどのような方法をとればよいでしょうか。
調べつつやっているのですが、なかなかうまくいかず・・・
お手数をおかけいたしますが、よろしくお願いいたします。

コード:

for(int i = 0; i < 4; i ++) {
int a = (bytes[i] & 0xff);
n = (n << 4) | a;
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C言語とJava間の通信について

#6

投稿記事 by beatle » 13年前

大雑把なやり方はあってます.

<< 4 の 4 はどういう根拠で4なのでしょうか.
byte型はJavaですと8ビットですから,4ビットシフトではなくて8ビットシフトしないとダメだと思います.
それから,int型が32ビットかどうか,C言語の規格では決まっていませんのでご注意ください.

jpex

Re: C言語とJava間の通信について

#7

投稿記事 by jpex » 13年前

返信遅れました。

8ビットですね・・・ようやく思うように動いてくれました!
たくさんのアドバイス本当にありがとうございます。
ビットに関する知識がまるでなかったので、これを機会に勉強してみます。

閉鎖

“C言語何でも質問掲示板” へ戻る