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

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

新規登録して質問してみよう
ただいま回答率
85.37%
バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

CRLF

CRLFは、改行コードのことです。 改行コードは、改行を表す制御文字です

Q&A

解決済

2回答

21879閲覧

C# シリアル通信のバイナリデータ受信

退会済みユーザー

退会済みユーザー

総合スコア0

バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

CRLF

CRLFは、改行コードのことです。 改行コードは、改行を表す制御文字です

0グッド

1クリップ

投稿2018/04/13 01:48

現在、VisualStudio2015 のWindowsフォームアプリケーションにてソケットを使用したシリアル通信のコードを書いています。

基本的な通信(送受信)はできるようになったのですが、受信メソッドにて

C#

1 //受信データのバイト数分蓄積 2 do 3 { 4 int length = ComPort.Read(buffer, readlen, rbyte - readlen); 5 readlen += length; 6 } while (readlen < rbyte); 7 recData += System.Text.Encoding.ASCII.GetString(buffer); 8 logText(recData, ComPort);

これで送られてきたByteをそのバイト分貯めてから
文字列に変換してテキストボックスにinvokeして書き込んでいますが、受信時にデータが分割されて送られてしまいます。

なので改行まで取得するように改良して以下のようにしました。

C#

1 // 受信データを改行まで蓄積 2do 3{ 4 int length = ComPort.Read(buffer, readlen, rbyte - readlen); 5 readlen += length; 6} while (readlen < rbyte); 7 recData += System.Text.Encoding.ASCII.GetString(buffer); 8 newline = recData.IndexOf(Environment.NewLine); 9if (newline >= 0) 10{ 11 logText(recData, ComPort); 12} 13else 14{ 15 Sendbuffa += recData; //データをいったん保存 16}

ですが、これだと一度の2回送信分のデータ(改行コードがふたつある)を受信してしまったときに、
1回送信分の中に改行コードが2つあると判断されてしまいます。
なので、改行コードを見つけたらその時点でテキストボックスに書きだしたいのですが、どう修正すればよいでしょうか。

尚、上記両コードとも表記したコードをCOMポート接続されている間ループさせております。

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

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

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

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

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

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

guest

回答2

0

文字列を流すのを前提とするなら、素直にReadline メソッドを使うなりしたほうがいいと思いますねー

投稿2018/04/13 02:43

y_waiwai

総合スコア88024

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

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

退会済みユーザー

退会済みユーザー

2018/04/13 03:46

y_waiwai 様 いつもコメントありがとうございます。  今は文字列のテストですがバイナリデータを扱えるものにしたいのでこのようにしております。
y_waiwai

2018/04/13 04:00

シリアルに限らず、TCPとかUDPとかの通信も含め、XXXバイト送信したのに、受信ではXXバイトとXXバイトに分けて受信される、XXバイトとXXバイトの2回送ったのにXXXXバイトにまとめて受信されてしまった というのはしごく当然の話となります。 それを前提としてコードを組む必要があります 一回の受信で改行が2つ受信されてしまったらどうしよう、というのではなく、受信イベントではとにかく今まで受信したデータを貯めていく、そして、その中から改行があればそこまでを1行として取り出す、という考え方で行かないとあとで苦労することになろうかと思います で、ReadLineメソッドというのは、上記の処理を実装しているんですね
退会済みユーザー

退会済みユーザー

2018/04/13 07:49

>>受信イベントではとにかく今まで受信したデータを貯めていく なるほどです。ReadLineのことを認識違いしていました。 これからなにかを受信するときは心がけるようにします!! ありがとうございます!
guest

0

ベストアンサー

こんにちは。
Split()関数を使って改行(\r\n)で分割してはどうでしょうか?

csharp

1 // 改行で分割 2 string[] lines = recData.Split( 3 new[] { Environment.NewLine }, 4 StringSplitOptions.None 5 ); 6 7 if (lines.Length > 1) 8 { 9 // lines[0] だけを送信して残りはバッファに詰めて次回 10 } 11 else 12 { 13 // lines[0]を送信して終わり 14 }

EDIT

記述が不親切だったのでコード例を記載します。

csharp

1 recData += System.Text.Encoding.ASCII.GetString(buffer); 2 var temporary = Sendbuffa + recData; 3 while (true) 4 { 5 newline = temporary.IndexOf(Environment.NewLine); 6 if (newline >= 0) 7 { 8 string[] lines = temporary.Split( 9 new[] { Environment.NewLine }, 10 StringSplitOptions.None 11 ); 12 logText(lines[0], ComPort); 13 14 if (lines.Length > 1) 15 { 16 // temporaryに残りを詰めなおす 17 temporary = temporary.Substring(newline + 2); 18 } 19 } 20 else 21 { 22 Sendbuffa = temporary; //データをいったん保存 23 break; 24 } 25 }

投稿2018/04/13 02:01

編集2018/04/13 03:14
g_uo

総合スコア212

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

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

退会済みユーザー

退会済みユーザー

2018/04/13 02:05

とても速いコメントありがとうございます! ひとつだけ質問なのですが、line[0]だけ送信とありますがlineの0要素目に改行コードを検出したところまでのデータが入っているのですか?
g_uo

2018/04/13 02:09

はいそうです。 recDataが "てすとデータです\r\n次のデータです\r\n" だったとすると、lines[0] は "てすとデータです"が格納されると思います。
退会済みユーザー

退会済みユーザー

2018/04/13 02:14

わかりやすいです!ありがとうございます! 残りのデータをバッファに移す時なのですが、 buffer = line[1]; だと次の改行までしか格納されないと思うのですが、まとめて「lineの1要素目以降」のようにまとめて格納することはできますか?
g_uo

2018/04/13 02:16

可能です。 回答が不親切だったので、回答のほうにコード例を記載しますのでしばらくお待ちいただけますか。
退会済みユーザー

退会済みユーザー

2018/04/13 02:21

お手数おかけしますすみません。 よろしくお願いいたします!!
g_uo

2018/04/13 02:36

編集しました。
YAmaGNZ

2018/04/13 03:05

横から失礼します。 Sendbuffa += temporary; だと、詰め直したデータが消えませんか? まぁ、元ソースがそうなっているんですけど。 また、データ詰め直しの部分の if (lines[1] == "\r\n") break; の部分は、必要ないのではないでしょうか?
g_uo

2018/04/13 03:12

> だと、詰め直したデータが消えませんか? └ 確かに消えます > の部分は、必要ないのではないでしょうか? └ 確かになくても問題ないですね 修正します。 けど、y_waiwaiさんの回答を採用するのがスマートですね
退会済みユーザー

退会済みユーザー

2018/04/13 03:50

皆さんコメントありがとうございます。 今回最終的にはバイナリデータに対応したいのでこのような質問内容にさせていただきました。 教えていただいたこと試してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問