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

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

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

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Q&A

2回答

3003閲覧

構造体メンバの配列へのファイル読み込みについて

cfu0987_APV

総合スコア15

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

0グッド

1クリップ

投稿2016/04/19 11:58

TCP通信における構造体メンバの配列へのファイル読み込みについて質問します。
TCPでビットマップと数値を送信するプログラムを作りました。
ネットを参考に下のプログラムを作り実行した結果、①の返り値は2500018を返しますが、受け取ったビットマップファイルには何も入っていませんでした(ファイルサイズ2.5M程度)。
そこで、②の返り値を見ると'0'でした。また、③の値は'19'でした。

〇質問
1.④で2.5Mのビットマップを読み込ませるために構造体(bmpfile[])のサイズを変えているのですが、この方法ではサイズの変更はできないのでしょうか。
2.もし質問1の方法が正しいとしたら、なぜ③でサイズ変更前の値が返ってくるのでしょうか。
3.①及び②の関数(send, fread)への引数への代入はこれで正しいでしょうか。

〇環境
OS:windouws7(SP1) 32ビットOS
開発:visual C++(2008)
メモリ:4GB
CPU:2.5GHz

〇プログラム
★struct.h

struct BMP_PIC{ unsigned short marker;//①マーカー unsigned long size;//②データバイト数 unsigned short tp;//③ヘッダ種別 unsigned short no;//④ヘッダ番号 float x;//数値1 float y;//数値2 unsigned char bmpfile[1];//ビットマップ用の配列(2.5Mを読み込ませる) } ;

★tTCP.cpp:

FILE *BMPFP; #define BMPTEST ".\\pic.bmp" BMPFP = fopen(BMPTEST, "rb"); struct BMP_PIC *m_BmpPic; fpos_t sz; fseek(BMPFP, 0, SEEK_END); fgetpos(BMPFP, &sz); m_BmpPic = (struct BMP_PIC *)malloc(sizeof(struct BMP_PIC) - 1 + sz);//④ m_BmpPic.marker = 0xABCD; m_BmpPic.size = sz + 8;//・・・実際のデータ(ビットマップ + 数値1 + 数値2)サイズを指定する。 m_BmpPic.type = 0; m_BmpPic.no = 0; m_BmpPic.x = 1000; m_BmpPic.y = 2000; sizeof(*m_BmpPic);//③ fread(m_BmpPic->bmpfile, 1, sz, BMPFP);//② send(s1, reinterpret_cast<const char*>(m_BmpPic), sz + 18, 0);//① free(m_BmpPic); fclose(BMPFP);

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

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

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

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

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

guest

回答2

0

szを採取するために fseekでファイルの終端に移動していますが
freadする前に fseekでファイルの先頭に戻さないといけないと思いますよ ・・・

投稿2017/08/20 11:54

mai-chan

総合スコア6

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

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

0

こんにちは。

1.④で2.5Mのビットマップを読み込ませるために構造体(bmpfile[])のサイズを変えているのですが、この方法ではサイズの変更はできないのでしょうか。

この方法で実質的なサイズ変更は可能です。といいますか、昔からC言語で良く使われるテクニックですね。

2.もし質問1の方法が正しいとしたら、なぜ③でサイズ変更前の値が返ってくるのでしょうか。

sizeof()演算子はコンパイル時に値が計算されます。
sizeof(*m_BmpPic);と記述した場合、m_BmpPicが指すメモリ領域のサイズではなく、*mBmpPicの型(この場合、BMP_PIC)のサイズになります。

3.①及び②の関数(send, fread)への引数への代入はこれで正しいでしょうか。

②は正しいように見えます。①は18という数字の意味にもよりますが、もしそれが、sizeof(struct BMP_PIC) - 1を意味している場合は期待通りの値になっていない可能性があります。
多くの処理系ではメンバ変数を配置する際、アクセスが高速になる位置に配置することが多いです。
そのような処理系では、unsigned longが4バイトの場合、4バイト境界(アドレスの下位2ビットが0)に配置されます。unsigned shortが2バイトだった場合、先頭のmarkerと次のsizeの間に2バイトのパディングが入る場合が多いです。アライメントと呼ばれます。
mallocの時と同様な計算式で計算されることをお勧めします。

①の返り値は2500018を返しますが、受け取ったビットマップファイルには何も入っていませんでした

上記ミスでは、恐らく最後の2バイトが欠けるだけですので、何も入っていないという状態にはならなさそうな印象です。小さい画像ファイルなら受け取れましたでしょうか?

投稿2016/04/19 12:47

編集2016/04/19 13:23
Chironian

総合スコア23272

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

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

cfu0987_APV

2016/04/20 12:36 編集

④の一つ前の行で”sizeof(struct BMP_PIC) - 1”の値を見ると"18"でこれは期待通りでした。 試しに50kバイトのビットマップ((H)240x(V)72, 色コード:ED1C24)を送信してみましたが、やはり正常には送れませんでした。受け取ったファイルをバイナリで開いてみるとヘッダ部含め全て"ADBA0DF0"で埋め尽くされていました。なので、読み込み(fread)に問題があるのでしょうか?
Chironian

2016/04/20 12:50

> ④の一つ前の行で”sizeof(struct BMP_PIC) - 1”の値を見ると"18"でこれは期待通りでした。 ということは、#pragma pack(1)されているのですね。 性能は若干落ちますが、有効範囲を必要最小限にしていれば問題ないです。 > 読み込み(fread)に問題があるのでしょうか? fread直後のデータを見てみれば分かるのでは? しかし、freadしていないヘッダまで化けているのであれば、freadの可能性は低いと思います。 例えば、データを0x55等で埋めて送ってみて、受信側で受け取れているのか確認するのも手と思います。 受け取れていないようでしたら、sendできているのか、recvできているのか?どちらかを切り分けるべきでしょう。そのような時はWireSharkが便利です。無償で使えるパケット・キャプチャです。http://beginners-network.com/wireshark.html
cfu0987_APV

2016/04/21 11:07

試しに0x55で全て書き込んだファイルを送った結果、受信ファイルは"ADBA0DF0"で埋められていました。また、②の後にfwrite(m_BmpPic->bmpfile, 1, sz, FP)を実行し作成したファイルも"ADBA0DF0"で埋められていました。なので、freadに問題があるように思えますが、これ以上どうしたらいいかがわかりません。
Chironian

2016/04/21 12:48

そのような時は、経験上ほぼ100%何か大きな単純な間違いをしています。 落ち着いて1つ1つ確認しましょう。 ・②の直後でダンプしてみて"ADBA0DF0"で埋められている。 ・その後で0x55でてデータを送ったのに受信側でも"ADBA0DF0"で埋められている。 この2つは独立な事象なので同じデータで埋められるというこは本質的にありません。 ということは、ダンプ方法をミスしている可能性が高いと思います。 どうしても判らないようでしたら、データを読んでダンプする部分なら、ソースをここに上げることが可能と思います。簡単にビルド/実行できる最小のソースとし、問題が再現することを確認した上で、ここで再度質問されると良いと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問