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

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

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

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

Q&A

解決済

2回答

5162閲覧

ファイル転送のプロトコルをC++で実装しているが、チェックサムのCRC16が合わない?どうして?

NEWBIEEBIEE

総合スコア62

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

0グッド

0クリップ

投稿2017/01/14 06:19

編集2017/01/14 06:42

ファイルの転送プロトコルのxmodemをLinux上で実装しているのですが、
ファイルを小分けにしたデータとそのチェックサムを送信して、
別の端末で受け取っています。しかし、このデータをその受け取った端末で
チェックサムを計算して、送られたチェックサムと照合すると一致しません。
写真では9404がデータと一緒に送られるのですが、データから再計算して出したチェックサムには7541とでます。
全く良くわからないのですが,これはファイルの受信のポインタ処理に問題があるのでしょうか、
ファイルを受け取る際にread関数で、配列をwhileで回すことによって、1024バイトのデータを取得しています。
そこでのポインタ処理に問題があるのでしょうか。バイナリとポインタは慣れていないので感覚がつかめません。

それとも、別の問題があるのでしょうか。

実行とエラー

送信側の処理(xymodem_send)

c++

1chunk.crc = swap16(crc16(chunk.payload, sizeof(chunk.payload)));

受け取り側の処理 (xmodem_receive)

c++

1 2 uint8_t recData[1024]; // receive data from chunk 3 uint16_t recChksum; 4 uint16_t recCRC; 5 6 // recData is data payload 7 ret = read(serial_fd, recData, sizeof(recData)); 8 9 printf("Data buffer is %c\n", &recData); 10 fflush(stdout); 11 12 // processing up to 1024bytes 13 if (ret != sizeof(recData)) { 14 rec_chunk_data += ret; 15 while(rec_chunk_data < sizeof(recData)){ 16 ret = read(serial_fd, recData + (sizeof(uint8_t) * rec_chunk_data), (sizeof(recData) - rec_chunk_data)); 17 rec_chunk_data += ret; 18 printf("ret is proceeding: %d\n", ret); 19 fflush(stdout); 20 } 21 } 22 23 ret = read(serial_fd, &recChksum, sizeof(recChksum)); 24 25 printf("Check sum is %d\n", recChksum); 26 fflush(stdout); 27 // Calculating checksum from data payload 28 recCRC = swap16(crc16(recData, sizeof(recData))); 29 // data integrity check 30 if(recChksum != recCRC){ 31 printf("Check sum is %d and %d\n", recChksum, swap16(crc16(recData, sizeof(recData)))); 32 perror("swap16"); 33 return -errno; 34 }

関係のある処理(コード)

c++

1#include <stdio.h> 2#include <stdlib.h> 3#include <stdint.h> 4#include <string.h> 5#include <errno.h> 6#include <unistd.h> 7#include <fcntl.h> 8#include <termios.h> 9#include <sys/types.h> 10#include <sys/stat.h> 11#include <sys/mman.h> 12#include <string> 13 14#define X_STX 0x02 15#define X_ACK 0x06 16#define X_NAK 0x15 17#define X_EOF 0x04 18 19 #define MAX_RETRY (9) 20 21#define min(a, b) ((a) < (b) ? (a) : (b)) 22 23struct xmodem_chunk { 24 uint8_t start; 25 uint8_t block; 26 uint8_t block_neg; 27 uint8_t payload[1024]; 28 uint16_t crc; 29} __attribute__((packed)); 30 31#define CRC_POLY 0x1021 32static uint16_t crc_update(uint16_t crc_in, int incr) 33{ 34 uint16_t xor1 = crc_in >> 15; 35 uint16_t out1 = crc_in << 1; 36 37 if(incr) 38 out1++; 39 40 if(xor1) 41 out1 ^= CRC_POLY; // xor 0b1000000100001 42 43 return out1; 44} 45 46 47static uint16_t crc16(const uint8_t *data, uint16_t size) 48{ 49 uint16_t crc, i; 50 51 for (crc = 0; size > 0; size--, data++) 52 for (i = 0x80; i; i >>= 1) 53 crc = crc_update(crc, *data & i); 54 55 for (i = 0; i < 16; i++) 56 crc = crc_update(crc, 0); 57 58 return crc; 59} 60 61static uint16_t swap16(uint16_t in) 62{ 63 return (in >> 8) | ((in & 0xff) << 8); 64} 65 66enum { 67 PROTOCOL_XMODEM, 68 PROTOCOL_YMODEM, 69}; 70

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

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

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

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

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

guest

回答2

0

こんにちは。

sizeof(recData)とsizeof(chunk.payload)は同じ値になるでしょうか?
一般的には、このような計算をする時、受信側は受信したバイト数を使います。

もし同じ値だった場合、payloadはいっぱいになってますか? もし、送信したバイト数より大きかった場合、空き部分に入っている値は、受信側の同様の空き部分に入っている値と一致してますか?

投稿2017/01/14 06:46

Chironian

総合スコア23272

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

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

NEWBIEEBIEE

2017/01/14 06:50

なるほど、確かにその通りでした。ちょっと確認してきます。
takotakot

2017/01/14 06:54

プログラムとしては、そこ、気になりますよね。
guest

0

ベストアンサー

直接の回答にはなっていません、ごめんなさい。

今回のような場合、

  1. 内容がごく短いテキストファイルを送信し、その内容を送り元、送り先の双方ですべて表示するようなデバッグ出力をし、その出力が同一かどうか検証する
  2. 同一である場合、それぞれ、「内容を埋め込んで CRC16 を計算する」
  3. sizeof(chunk.payload) 等、crc16 の引数の中身が同一か検証する

ことで、切り分けが可能ではないかと考えます。参考にしてください。

http://stackoverflow.com/questions/41647161/why-my-checksumcrc16-in-uart-is-not-matched
には書きませんでしたよ。

よろしくお願いいたします。

投稿2017/01/14 06:54

takotakot

総合スコア1111

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

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

NEWBIEEBIEE

2017/01/14 06:56

う〜ん、やってみます。(まさかみられてるとは・・・・・)
NEWBIEEBIEE

2017/01/14 07:33

ありがとうございます。1と2をやってみたところ、どうやら再計算のところで間違えているようです。(とりあえず途中まで)
NEWBIEEBIEE

2017/01/14 08:24

3に関しては2回め以降が一致しないようです。正直う〜んという感じです。
takotakot

2017/01/14 08:42

sizeof(recData) ということは、1024 固定ですよね、後ろの0埋めとかかもしれませんね。 がんばって切り分けてみて下さい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問