VisualC++6.0にて、PCと通信相手の機械との間で、同期のシリアル通信を行うツールを作成していますが、たまにWriteFile()のデータ送信が完了しない状況になってしまいます。
問題が発生している状況は、以下となります。
・WriteFile()を実行した際、戻り値としてTRUEが返却されるが、書き込んだバイト数が0byteとなっていて、送信できていない。
・上記問題が発生した際でも、ReadFile()でのデータ受信は正常に出来る。
・WriteFile()やReadFile()の実行前後でClearCommError()を実行しても、いずれもオーバーフロー等のエラー情報は検出できない。
・上記問題が発生した際、GetLastError()=0となり、エラー情報は検出できない。
・ツールを最小化したり、IE等のプログラムを立ち上げたりした際に、上記問題が発生しやすい。
・DCB構造体のfDtrControlとfRtsControlをDISABLEやENABLEに変更したが、状況は改善しなかった。
・VisualStudio2005のC++にてツールを作り直したが、状況は改善しなかった。
・処理中にSleep(1)を入れて、WriteFile()とReadFile()の間隔を広げると問題は発生しなくなる。ただし、ツールの処理時間が倍以上となってしまう為、Sleepを入れることでの解決はしたくない。
また、PCと通信相手の機械との間の通信内容は、以下となります。
・上記問題が発生するまでの通信は、正常にできている。
・シリアル通信は、仮想COMポートによるUSB2.0の通信。
・SetCommTimeouts()にて、Read/Write共に、タイムアウト時間を1500msとしている。
・通信相手からの1回あたりのデータサイズは、最大4100kByte。また、5分間で約500MByteのデータがPC側へ通知される。
・PCからは、通信相手からのデータを受信した後、ACKとして8Byteのデータを送信する。
・PCは、USB2.0に対応したWindowsXPとVistaで上記問題が発生することを確認した。
私としては、問題が起こるまでの通信は正常に出来ている点や、Sleepを入れることで、問題が発生しなくなる点から、ツールの不具合ではなく、PC内部でデータ送信できなくなる問題が発生しているのではないかと考えています。しかし、問題の特定には至っていません。
どうか上記問題として考えられる原因や、原因特定の為の調査方法をご教示ください。
よろしくお願いします。
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
おはようございます。
「仮想COMポート」って事は、RS232Cとかのシリアル通信ではなく、FTDIとかのUSBによる通信なんですよね。
速度もすさまじいですしね。
なんかこうなってくると、ドライバを疑ってみたくなってしまいますが・・・。
同期モードでやられているとの事ですが、シリアル通信は必ず非同期モードで、と、どこかで読んだ記憶があります(多分、速度上の理由であり、本件とは関係ない気もしますが)。
「GetOverlappedResult」で検索すれば、サンプルがいっぱい出てきますので、非同期を完成させてみられてはどうでしょう。
当方では、以下のような感じで正常に通信ができていますので、ご参考になれば。
・相手はFT245BL(FTDI)
・非同期モード
・受信は別スレッド
・通信データ量は質問者様よりはるかに少ないですが、少量のデータをひっきりなしにやり取りしています。
回答ありがとうございます。
私も初めはドライバが処理速度についていけてないのではと考えていました。
その為、別のドライバを使用して動作検証を行ってみましたが、結果は改善しませんでした。
また、使用しているドライバは私が作ったものではなく、ドライバや通信相手の機械を修正することが出来ない為、ツール側で問題を解決したいと考えている次第です。
やはり、高速な通信の場合には、非同期モードにて通信を行ったほうがいいようですね。
非同期モードにて何とか解決できる方法がないかと、本問題の根本原因について、引き続き調査していきます。
No.3
- 回答日時:
WriteFileのリファレンスはちゃんと読まれましたか?
オーバーラップをつかって書き込んだ場合hFileのオープン時にFILE_FLAG_OVERLAPPDを指定し、lpOverlappedに有効なポインタが渡された場合 WriteFileは 0を返します
この時点では まだ転送が完了していないので GetLastErrorもERROR_IO_PENDINGを返し、まだデータ転送が終わっていないことを示します
転送できたどうかは GetOverlappedResultで取得するのですよ
本来ならhEventにCreateEventで作成したハンドルを設定しておいて
WaitForSingleObjectなどでこのイベントハンドルがシグナル状態になるのを待機して、待機が解除されたらGetOverlappedResultで確認
といった手法でしょう
本当にオーバーラップが必要なのでしょうか?
通信相手のマニュアルにはサンプル例などがないのでしょう …
この回答への補足
通信モードは、同期モードにて通信をおこなっています。
(CreateFile()にてFILE_FLAG_OVERLAPPEDを設定していません。)
また、非同期モードにて通信を行うように処理を修正しても、問題は改善しませんでした。
(詳細は、No.2の回答の補足として記載しています。)
No.2
- 回答日時:
こんにちは。
非同期モードでオープンされているのですよね。
概ね非同期通信の想定通りの動作のように思えます。
GetLastErrorが0を返すというのが気になりますが。。。
GetOverlappedResultで、送信完了を待つとかされては、どうでしょう。
この回答への補足
回答ありがとうございます。
通信モードは、同期モードにて通信をおこなっています。
(CreateFile()にてFILE_FLAG_OVERLAPPEDを設定していません。)
また、以下のように非同期モードにてデータ送信を行うようにツールを作り直した事もありました。
(1)WriteFile()にてデータ送信を開始する。
(2)WaitForSingleObject()にてシグナル状態になるまで待機する(1000msでタイムアウト)。
(3)(2)にてシグナル状態になった際に、GetOverlappedResult()にて送信完了したデータサイズを取得する。
上記の結果としては、(2)にてタイムアウトとなり、(3)まで処理が進みませんでした。
その際、GetLastError()=997(ERROR_IO_PENDING)となりました。
また、SetCommTimeouts()やWaitForSingleObject()でのタイムアウト時間を延長しましたが、結果は変わりませんでした。
その為、同期モードでも非同期モードでも発生する問題であると考えて、現状は同期モードにて問題の調査を行っている次第です。
No.1
- 回答日時:
WriteFile()は単にバッファにデータを転送するだけで実際のシリアル通信とは連動しません。
(通常はほぼ同時に終了)ただし他のアプリケーションが動作していたり、最小化していれば実際の通信が終了しないことは十分に有り得ます。
lpNumberOfBytesWrittenがnNumberOfBytesToWritより小さい時Sleepを入れる、GetQueuedCompletionStatus()によって送信完了を確認するなどで解決できるのでは。
この回答への補足
回答ありがとうございます。
lpNumberOfBytesWrittenがnNumberOfBytesToWritより小さい時Sleepを入れるという方法は試してみましたが、解決出来ませんでした。
現状は、WriteFile()でのデータ送信が出来なくなったら、一度USBケーブルを抜かないと
正常にデータ送信できなくなる状況です。
GetQueuedCompletionStatus()というものは、使用したことはありませんが、以下のサイトで存在自体は知っていました。
http://keicode.com/windows/win06.php
しかし、サーバー開発に用いられると説明されていた為、今回のようなシリアル通信には使用できないと思っていました。GetQueuedCompletionStatus()は、シリアル通信にも用いることが出来るものなのでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) EXCELの外部データ取得ができない 1 2023/03/23 09:03
- デスクトップパソコン 通話が遅延します 1 2023/06/18 02:36
- ガラケー・PHS SMSメールの受信遅延原因はガラケー自体の欠陥では 8 2022/08/06 11:46
- Outlook(アウトルック) OCN WEBメールについて 1 2022/05/18 23:33
- モニター・ディスプレイ 長文です。デスクトップPCのHDMI入力機能について 4 2022/09/20 17:58
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- Wi-Fi・無線LAN 最近、WiFiの問題でPCがろくに使えないのですがどうすればいいですか。 現在、何らかの原因でPCを 5 2023/02/19 12:52
- ガラケー・PHS 携帯電話の居場所信号の発信タイミング 3 2022/07/27 14:39
- 中学校 娘のクラスの学級通信に個人情報が掲載されていて、非常に不快です。 7 2022/04/22 18:02
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
このQ&Aを見た人はこんなQ&Aも見ています
-
性格の違いは生まれた順番で決まる?長男長女・中間子・末っ子・一人っ子の性格の傾向
同じ環境で生まれ育っても、生まれ順で性格は違うものなのだろうか。家庭教育研究家の田宮由美さんに教えてもらった。
-
シリアル通信の出力バッファと送信完了イベントについて
C言語・C++・C#
-
シリアル通信の受信待ちについて
C言語・C++・C#
-
CreateFile関数でCOMポートが開けない
C言語・C++・C#
-
-
4
WriteFileで送信できたかの確認方法は?
C言語・C++・C#
-
5
ReadFileの読み込みエラーについて
C言語・C++・C#
-
6
WriteFileの引数について
Mac OS
-
7
CString から LPCTSTRの型に変換
C言語・C++・C#
-
8
シリアル通信時のデータ受信方法
Visual Basic(VBA)
-
9
RS232cを用いた送信プログラム
C言語・C++・C#
-
10
画面を強制的に再描画させる方法
C言語・C++・C#
-
11
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
12
ConnectNamedPipeの接続待ち
C言語・C++・C#
-
13
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
14
エクセル VBA でのCOMポート認識
その他(プログラミング・Web制作)
-
15
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
16
シリアル通信で0x00を送信したいのですが。
C言語・C++・C#
-
17
シリアル通信 大きいサイズの受信処理
C言語・C++・C#
-
18
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
19
シリアルの送信完了を待つ方法
UNIX・Linux
-
20
char*を初期化したいのですが
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Connection reset by peer
-
C# シリアル通信でデータ受信...
-
waveIn、waveOutでの音声録音・...
-
VB2005でWin32APIを用いてRS-23...
-
「スイッチングハブのバッファ...
-
rs232cでの受信データ(mscomm)...
-
COMポートの同時オープン同時読...
-
visual c# 2010 シリアル通信ア...
-
VB2010 シリアル受信した情報を...
-
【CAsyncSocket::OnReceive()呼...
-
RS232C通信(PC⇔PLC)
-
Linuxでのシリアル通信について...
-
MSCommでoutputできない
-
winsockでソケット通信の開発を...
-
シリアル通信 大きいサイズの...
-
RS232C通信のC言語プログラム:...
-
Macターミナルで実行中のプログ...
-
緯度、経度の 10進法と 60進法...
-
バックグラウンドのプロセスの...
-
TCP/IP通信時のサーバーからの受信
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
winsockでソケット通信の開発を...
-
socket: recvはいつ,どれだけ...
-
SocketのSend関数でのCLOSEの検...
-
シリアル通信の出力バッファと...
-
WriteFile()でのデータ送信がで...
-
RS232C通信(PC⇔PLC)
-
シリアルポート通信
-
ソケット通信内 read関数について
-
Linuxでのシリアル通信について...
-
SerialPortのDataReceivedイベ...
-
「スイッチングハブのバッファ...
-
Connection reset by peer
-
RS-232Cでバイナリデータを受信...
-
UDP処理のエラーについて
-
VB2005でWin32APIを用いてRS-23...
-
シリアル通信エラー
-
winsockの動作について。
-
シリアル通信 大きいサイズの...
-
VB2010 シリアル受信した情報を...
おすすめ情報