質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

2438閲覧

2byte以上の数値データ送信

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2015/11/26 20:32

2byte以上のデータ送信について
int 型のデータ4つを送信するためにプログラムを書いたのですがうまく動きません.
ご指摘ください.

送信側

ruby

1first = 0x00000001 2second = 0x00000000 3third = 0x00000000 4fourth = 0x00000000 5 6msg = [first,second,third,fourth].pack("N*") 7socket.write(msg) 8#これでネットワークバイトオーダでunsigned long * 4のデータサイズで書き込めるはず

受信側

C++

1 struct node *tmp; 2 if(recv(socket,tmp,sizeof(char) * 16,0) < 0) 3 perror("ID ERROR"); 4 tmp->n_ntoh(); 5//受け取ったデータをネットワークバイトオーダからホストオーダに変換して 6//値をとり出すことを目標 7 8 9//以下は他の部分でされている定義 10 typedef struct node { 11 uint32 first; 12 uint32 second; 13 uint32 third; 14 uint32 fourth; 15 void n_ntoh(void){ 16 first = ntoh(first); 17 second = ntoh(second); 18 third = ntoh(third); 19 fourth = ntoh(fourth); 20 } 21 };

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

C/C++側への回答となります。

原因1 tmpの実態がどこにもない。
struct node work;
struct node *tmp = work;
とする。でもこれは無いと思う。理由はChironianさんの仰っている通り。
原因2 uint32が32bit整数じゃない。
uint32_tを使う。
原因3 関数ntohが期待の通りに動いていない。
ntohlではないか?????
原因4 受信が分割されている。recvは取りこぼすこともある。
int i,r;
char *p = (char *)tmp;
for ( i = 0 ; i < 16 ; ){
if ((r = recv(socket, p+i, 16-i, 0)) < 0) {
perror("ID ERROR");
} else {
i += r;
}
}
として、取りこぼしをなくす。
原因5 通信できてない
まず、通信できるようにする。問題のコードはもっと前にある。

今の情報ではこのくらいのような気がします。

そもそも論ですが、C/C++はソースを読んで構造体の占有メモリサイズを数える事は出来ないのですよ。
メンバfirstとメンバsecondの間に、アライメント調整の為のゴミがあってもOKな言語ですからね。
上記を考慮すると、cateyeさんが言っておられるように配列に読ませないといけません。
struct node {
uint32_t first[4]; <--- ここに読ませる
void n_ntoh(void){
first[0] = ntohl(first[0]);
first[1] = ntohl(first[1]);
......
}
};
まぁ、
・ターゲットマシンが固定。
・コンパイラが固定。
・構造体での割り付けルールは全て分かっている。
ならば、構造体に読み込んでも良いのかもしれませんが、他の人はどうしてるんでしょうね。

投稿2015/11/29 00:46

編集2015/11/30 13:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「うまく動かない」では分かりません。どううまく動かないのか書いてください。

Rubyは分からないので、C++で気が付いた事だけですが・・・
struct node *tmp;はポインタですが実態はどこにあるのでしょう?
・・・そもそもソケットは通信できていますか?

投稿2015/11/26 20:46

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/11/26 21:48

すいません 補足すると, 送信側ではサイズを調べてみると16となっており16byte のデータが送信できています. 受信側ではうまくデータを受け取れておらず, データには文字化けした文字が入っているだけです. 構造体にバイトストリームのデータを書き込むのはこの方法であっているのでしょうか?
cateye

2015/11/27 14:19 編集

送受信が出来ているかどうか・・・ 通信内容については、サイズの問題もあるので、Wiresharkなどのネットワークモニタで送受信データを確認するほうが確実です。 受信方法はuint32の配列(メモリが連続しているのが保障される)で受けて受信データをn_ntoh()に渡すほうがいいのではないでしょうか? あと今気が付いたのですが^^; first = ntoh(first);の左辺のfirstは分かりますが右辺のfirstは何なんでしょう? また、ntoh()は何なんでしょう?・・・ntohl()の事でしょうか? 参考:http://wisdom.sakura.ne.jp/system/winapi/winsock/winSock4.html
guest

0

こんにちは。

cateyeさんも指摘されてますが、受信バッファの与え方を間違っているように思います。
C/C++言語に慣れない内はよくやってしまうのですが、ドキュメントに

C++

1size_t recv(int s, void *buf, size_t len, int flags);

と記載されている時、ついbufに初期化していないポインタを渡してしまうのですよ。
struct node *tmp;ではtmpに値を設定していないので、不定値が入っています。

では、recv()のbuf引数に何を渡すべきかというと、受信バッファへのポインタですね。
例えば、'struct node tmp;でスタック上にメモリが確保されます。 そして、&tmptmp`へのポインタになります。

受信側ではうまくデータを受け取れておらず, データには文字化けした文字が入っているだけです.

不定な値をrecv()関数へ渡している場合アクセス違反で落ちることが多いです。
受信バッファの中身を確認できたということは落ちていないはずですから、別の原因があるかも知れません。
そもそも、cateyeさんのご質問通り、受信できているのかどうか確認下さい。
if (recv(...) < 0)では不十分です。何バイト受信できているか確認しましょう。

それと、「文字化け」ですか? 送っているデータは「文字」ではないですよね?

頑張ってください。


最後に、ついでです。sizeof(char) * 16は無意味に複雑な記述です。単純に16としてしまうか、sizeof(struct node)とすると良いです。後者の使い方はまさにsizeof演算子の代表的な使い方です。

投稿2015/11/27 01:17

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問