• 締切済み

WriteFile()でのデータ送信ができなくなる

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内部でデータ送信できなくなる問題が発生しているのではないかと考えています。しかし、問題の特定には至っていません。 どうか上記問題として考えられる原因や、原因特定の為の調査方法をご教示ください。 よろしくお願いします。

みんなの回答

  • pyonmae
  • ベストアンサー率64% (40/62)
回答No.4

おはようございます。 「仮想COMポート」って事は、RS232Cとかのシリアル通信ではなく、FTDIとかのUSBによる通信なんですよね。 速度もすさまじいですしね。 なんかこうなってくると、ドライバを疑ってみたくなってしまいますが・・・。 同期モードでやられているとの事ですが、シリアル通信は必ず非同期モードで、と、どこかで読んだ記憶があります(多分、速度上の理由であり、本件とは関係ない気もしますが)。 「GetOverlappedResult」で検索すれば、サンプルがいっぱい出てきますので、非同期を完成させてみられてはどうでしょう。 当方では、以下のような感じで正常に通信ができていますので、ご参考になれば。 ・相手はFT245BL(FTDI) ・非同期モード ・受信は別スレッド ・通信データ量は質問者様よりはるかに少ないですが、少量のデータをひっきりなしにやり取りしています。

bunbun0c0
質問者

お礼

回答ありがとうございます。 私も初めはドライバが処理速度についていけてないのではと考えていました。 その為、別のドライバを使用して動作検証を行ってみましたが、結果は改善しませんでした。 また、使用しているドライバは私が作ったものではなく、ドライバや通信相手の機械を修正することが出来ない為、ツール側で問題を解決したいと考えている次第です。 やはり、高速な通信の場合には、非同期モードにて通信を行ったほうがいいようですね。 非同期モードにて何とか解決できる方法がないかと、本問題の根本原因について、引き続き調査していきます。

  • kimi2807
  • ベストアンサー率33% (1/3)
回答No.3

WriteFileのリファレンスはちゃんと読まれましたか? オーバーラップをつかって書き込んだ場合hFileのオープン時にFILE_FLAG_OVERLAPPDを指定し、lpOverlappedに有効なポインタが渡された場合 WriteFileは 0を返します この時点では まだ転送が完了していないので GetLastErrorもERROR_IO_PENDINGを返し、まだデータ転送が終わっていないことを示します 転送できたどうかは GetOverlappedResultで取得するのですよ 本来ならhEventにCreateEventで作成したハンドルを設定しておいて WaitForSingleObjectなどでこのイベントハンドルがシグナル状態になるのを待機して、待機が解除されたらGetOverlappedResultで確認 といった手法でしょう 本当にオーバーラップが必要なのでしょうか? 通信相手のマニュアルにはサンプル例などがないのでしょう …

bunbun0c0
質問者

補足

通信モードは、同期モードにて通信をおこなっています。 (CreateFile()にてFILE_FLAG_OVERLAPPEDを設定していません。) また、非同期モードにて通信を行うように処理を修正しても、問題は改善しませんでした。 (詳細は、No.2の回答の補足として記載しています。)

  • pyonmae
  • ベストアンサー率64% (40/62)
回答No.2

こんにちは。 非同期モードでオープンされているのですよね。 概ね非同期通信の想定通りの動作のように思えます。 GetLastErrorが0を返すというのが気になりますが。。。 GetOverlappedResultで、送信完了を待つとかされては、どうでしょう。

bunbun0c0
質問者

補足

回答ありがとうございます。 通信モードは、同期モードにて通信をおこなっています。 (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()によって送信完了を確認するなどで解決できるのでは。

bunbun0c0
質問者

補足

回答ありがとうございます。 lpNumberOfBytesWrittenがnNumberOfBytesToWritより小さい時Sleepを入れるという方法は試してみましたが、解決出来ませんでした。 現状は、WriteFile()でのデータ送信が出来なくなったら、一度USBケーブルを抜かないと 正常にデータ送信できなくなる状況です。 GetQueuedCompletionStatus()というものは、使用したことはありませんが、以下のサイトで存在自体は知っていました。 http://keicode.com/windows/win06.php しかし、サーバー開発に用いられると説明されていた為、今回のようなシリアル通信には使用できないと思っていました。GetQueuedCompletionStatus()は、シリアル通信にも用いることが出来るものなのでしょうか。

関連するQ&A

  • HIDでReadFileのタイムアウトを設定したい

    PCとUSB接続したHIDデバイスと通信するのに、CreateFileからWriteFile/ReadFileを使用しています。 VID、PIDを頼りに、通信自体は問題なくできています。 ただし、デバイス側のモード切替で、通信モードに入っていないときに問題が発生します。 WriteFileのほうはデバイスがつながってさえいれば送信だけはできるので一応問題ないのですが、ReadFileのほうはデバイスが通信モードに入っていないときでもデバイスからの受信待ちを続けて処理がストップしてしまいます。 SetCommTimeoutsでタイムアウトの設定をできないかとやってみたのですが、「ファンクションが違います」というエラーがでるばかりでなんともなりません。 こいつはシリアル通信のときにしか使えないのでしょうか。 HIDデバイスとの通信でタイムアウトを設定する方法はないものでしょうか? あるいは受信待ちでストップしないよい方法はないでしょうか?

  • パイプを用いたプロセス間通信について

    VC++2005にて下記サイトを参考にパイプを用いたプロセス間通信を行うプログラムを作成しています。 猫でもわかるプログラミング (1)第242章 匿名パイプ(サーバー側) http://www.kumei.ne.jp/c_lang/sdk3/sdk_242.htm (2)第243章 匿名パイプ(クライアント側) http://www.kumei.ne.jp/c_lang/sdk3/sdk_243.htm サーバー側からWriteFileでデータを送信する際に、 char型配列に入ったバッファデータ「szBuf」を送信し、 クライアント側のReadFileで同じく「szBuf」で受信していますが、 構造体Data ================== typedef TypeData{ int a; int b; char c[10]; }Data; ================== のオブジェクトdataを送信するには、WriteFile及びReadFileの箇所は どのように実装すれば良いのでしょうか? MSDNにはWriteFileの引数の型はLPCVOIDとあるため、 可能だと思うのですが。。。 もし解決策をご存知の方おられましたら、ご教示お願い致します。

  • COMポートに流れるデータを監視する方法について

    ComPortキャプチャのような COMポート(シリアルポート)を経由してやりとりされる送受信データをキャプチャするツールを作成しようとしております。 言語は、C言語でBCCdeveloperの環境で 作成しております。 WIN32APIの下記の関数でなんとか 送受信できるツールは、できました。 CreateFile GetCommState ClearCommError WriteFile ReadFile ひとつのツールでポートをオープンすると 別のソフトからはオープンできないようなので、 なんとかして、他のソフトが送受信しているデータを キャプチャできる方法ありましたらご教授願います。

  • ReadFile処理時のCPU使用率について

    はじめまして。 C++Builderの6.0で開発をしているものですが、現在、シリアル通信のモジュールを作成していて、ReadFileを用いて受信側の処理を行っています。ですがステップ実行させてみるとReadFile処理時のCPU使用率が100%になってしまいます。一方、送信のWriteFileではCPU使用率は上がりません。この現象について解決策があれば教えてください。 よろしくお願いします。

  • 送信したデータの一部が文字化けしちゃう

    ソケット通信を利用してデータを送信した際に、 データの一部が文字化けしてしまって困っています。 Cのプログラム内でデータを作成し、 writeを使用してソケットディスクリプタに書き込んでます。 デーモンを介してJavaのプログラムに送信しているのですが、 writeする直前では正常なデータなのに、 Java側で受信すると一部の文字が化けてしまうことがあります。 原因とかぜんぜんわからなくて、かなり困ってるのですが、 わかる方いらっしゃいましたら教えてくださぁ~~~いっ! お願いします!!! ちなみに、送信しているデータは構造体です。

  • Thunderbird で送信できません。

    新しいPC(Vista Ultimate)に移行するのでこの際メーラーをDatulaからThunderbirdに変更しようと思いました。設定も順調に進み、データの移行も完了したのですが、メールの送信ができません。受信の方は問題ありません。Mozillaのページを含め色々調べたのですがうまくゆかないのでここでお聞きします。 <送信を押すとパスワードを聞いてくるので入力します。パスワードの保存にチェックを入れて、OKを押します。するとまた同じダイアログが開いて先に進めません。> ・このときタスクマネージャで見ていると通信している気配が見られません。 ・セキュリティソフトを停止しても状況は変わりません。 ・新しいプロファイルを作ってやり直しても同じです。 ・アンインストールして再インストールしても同じです。 ・Thunderbird2.0.0.14、12、06のいずれでも同じ症状です。 ・Gmailアカウントからの送信は正常にできます。 何か他に試してみることはありますでしょうか。 Thunderbirdはレジストリを使っていないのでしょうか。もし使っているなら完全にアンインストールする方法はないでしょうか。(クリーンインストールしてみたいので)

  • フレッツADSLで、あるサイズ以上のデータが送信できない

    フレッツ ADSL 8M の共用タイプを導入しましたが、データの送信に問題が発生しています。 【現象】1.http で、特定サイトの特定ページ(CGI呼び出し:http://www.hoge.com/aaa.cgi?a=xxx&b=zzz など)が表示されない。     2.http で、特定サイトの特定ページ(BBSなど)のフォームが送信できない。     3.上記問題の原因がブラウザにあるか、それ以外にあるかを切り分けるため      smtp(メール送信)、ftp(ホームページスペースへのアップロード)での送信を      行ったところ、500バイト程度のデータは正常に送信されるが、800バイト程度以上のデータでは、      タイムアウトが発生するまで通信がストップし、送信できない。 【環境】OS:Windows 2000 professional + SP2     NIC:メルコ社製 LGY-PCI-TXC(ドライバ Ver. 1.02)     モデム:NTT社製 ADSLモデム-MS     ISP:リムネット     セキュリティソフト:Symantec社製 Norton Internet Security 2002  フレッツADSL なので、MTUを 1454に調整しました。  フレッツ接続ツールをやめ、RasPPPoE に替えてみましたが状況は変わりません。  ISPに問い合わせたところ、ルータのフィルタ設定かセキュリティソフトの設定が原因の 可能性があると回答がありましたが、ルータは使用しておらず、ADSLモデムにフィルタ機能 はない為問題なし、セキュリティソフトがブロックした場合は警告メッセージが表示されるか ログ出力される筈なので、メッセージもログ出力もない事からこれも問題なしと考えています。 もちろん、Windows 2000 標準のフィルタ機能やルーティング機能は使用していません。  他に考えられる原因はありますでしょうか?

  • データ受信ができません

    現在、Turbo C++を用いてソフトを作っています。WinAPI関数を用いて、RS232Cによって電子回路とPC間でシリアル通信を行っています。デスクトップのパソコンでは通信はうまくできていたのですが、ノートパソコンに、USBとRS232Cの変換ケーブルを用いて同じプログラムを動かしたところ、データ受信が全くされません。CreateFile関数はエラーは出ませんが、ReadFile関数などは受信されずに待機しているような状況です。コムポートの設定も問題はないと思うのですが、他に何か問題はあるでしょうか。 予想できる範囲でわかる方お願いします。

  • データ送信について

    今まで使用していたPC(Windows xp)が壊れてしまい、修理に出す為もう一台買いましたが、PC(Windows xp)USBケーブルでデータ送信をしようとしたが、ドライバCDが全く読み込めないという状況になってしまい、どうにもできなくなってしまいました。他にデータを移す方法はありますか?初心者です。

  • 大量データ送信を制限する方法 OCN

    先日OCN様より 【OCNからの重要なお知らせ】大量データ送信による利用停止および契約解除のご連絡 といった文面の書類が届きました。 内容は大量データ送信が確認できたので、1日30GB以上の通信を今後も続けるようなら契約を解除するといった内容です。 大量データ送信には心当たりがあるので(ウェブカメラ・Skypeでの長電話・ネットゲームなど)制限する事には構わないのですが、自分がどの程度の通信量をしてるのかわからないまま契約解除となると困ります。 そこで、自分の通信量を確認出来るツールなどは無いでしょうか? また、通信量を制限するツール(1日30GB使用したら自動で通信を遮断など)などは無いでしょうか?

専門家に質問してみよう