MSComm通信で35000文字相当の転送について


akit  2005-12-21 14:40:17  No: 129131

MSCommを用いて、PC間のRS232C通信を行っております
送信側のPCから約3万5千相当の半角英数文字列を送信しております

それが受信側のPCがうけっとたデータを見てみると
約5000相当のデータしかありません

MSCommの通信において、送信データの上限とかあるのでしょうか?
設定方法とかがあるのであればお教えください
お願いします


GOD  2005-12-21 15:37:45  No: 129132

>MSCommの通信において、送信データの上限とかあるのでしょうか?
>
受信側のプログラム次第じゃないですかね。
どのようなコードをどこのイベントで書いてます?(受信部分)

例.
Public Sub Command1_Click()
    Text1.Text = Mscomm1.Input
End Sub
↑みたいに書いて実験しているなら一度に受信できる最大値は受信バッファサイズです。


akit  2005-12-21 15:41:46  No: 129133

do
    doEvents
    Text1.Text = Mscomm1.Input
loop

MSComm1.InBufferSizeをいろいろ変えてみたのですが変化はありませんでした

ちなみに通信速度を上げてみたら、受信データは増えたのですが
どうしても通信速度9600で行いたいのです。


あの  2005-12-21 16:34:04  No: 129134

Text1.Text = Mscomm1.Input
これじゃ後から来たデータで次々上書きされてしまいますが。


akit  2005-12-21 16:50:26  No: 129135

書き間違えました

Text1.Text=Text1.Text &  Mscomm1.Input

にしています。

速度9600で行った場合、送信側のOutBufferCountと
受信側のInBufferCountをいくつにしても
受信側には4816文字までしか受信されませんでした
何回実行してもこの結果です。
ちなみにポートは常に開いていて閉じる処理は実行されていません。


我龍院忠太  2005-12-21 17:25:31  No: 129136

>速度9600で行った場合、送信側のOutBufferCountと
>受信側のInBufferCountをいくつにしても
何の為にそんなものをいじっているのかな。
InBufferSizeやOutBufferSizeで有ればとりあえず
デフォルトのまま動かさない方がいいのでは。

それとRS232Cの場合送受信でワンセットなので、両方の
コードを見ないと、判断は難しいと思われる。


あの  2005-12-21 17:52:24  No: 129137

とりあえずエラーが起こっても気にせず受信みたいなプログラムなので
ちゃんとOnCommイベントの中で受信した方がいいんじゃない?
まずはMSDNライブラリのMSCommコントロールのサンプルを見て下さい。


我龍院忠太  2005-12-22 07:54:31  No: 129138

PC間の通信だったら、エラーは「受信バッファ・オーバーフロー」
位でしょう、FlowControlをXon/Xoffにしといた方が良いでしょう。
ポーリングでデーターを受け取るにしろ、イベントドリブンの
OnCommでデーターを受けるにしろ、データー送信の終わりを
送信側から受信側に知らせるか又は受信開始からのタイマーで
強制的に受信を終了する必要は有りますね。

長いデーターを
>Text1.Text=Text1.Text &  Mscomm1.Input
の方法はかなりお勧めできない方法ですが,現在4816文字までしか
受信できてないなら、とりあえずは次の問題かな。


ひろ  2005-12-24 00:00:03  No: 129139

MsCommには送信できるバイト数の制限は決まっていないようですが、
「送信所要時間」
の制限があるようです。

MsCommの問題かそれよりも下の層の問題なのかはわかりませんが、ある秒数よりも長い送信時間を要する送信は、途中で送信が打ち切られてしまい、その時点で送信完了イベントが発生し、残りのデータは闇に捨て去られてしまいます。

手元に資料がないので詳細は思い出せませんが15秒ぐらいのところで限界があったはずです。

自分がこの現象に気づいたのは、300bpsで500バイトぐらいの送信をしようとした時で、送信データが受信側に正しく渡らずに途中で切れてしまいました。しかも、なぜか送信速度を上げると正常に転送できるのです。
散々調べた挙句、コミュニケーションアナライザを持ち出してきて調べたら送信側が勝手に送信を途中でやめてしまっていることがわかりました。

解決策として、送信条件から推定される送信時間が10秒を超える場合は複数回に分けて送信することをお勧めします。


我龍院忠太  2005-12-24 14:16:46  No: 129140

>「送信所要時間」
>の制限があるようです。
WindowsならSetCommTimeoutsが有ります。
http://www.microsoft.com/japan/developer/library/jpwinpf/_win32_setcommtimeouts.htm
設定値を見るにはGetCommTimeoutsを使います。
http://www.microsoft.com/japan/developer/library/jpwinpf/_win32_getcommtimeouts.htm
ただしデフォルトでは設定されていないと思ったが・・


ひろ  2005-12-27 08:53:12  No: 129141

> 手元に資料がないので詳細は思い出せませんが15秒ぐらいのところで限界があったはずです。

5秒でした。


ひろ  2005-12-27 09:09:20  No: 129142

途中で送信してしまったのでその続き。

データ長8ビット、パリティ無し、ストップビット1ビットと仮定すると1バイト送信するのに、10ビット分の送信時間が必要なので、9600bpsだと 9600/10*5 = 4800なので5秒で約4800バイト
ということで、akitaさんの現象も5秒制限にひっかかってしまった可能性が高そうですね。


ひでらん  2005-12-27 11:46:03  No: 129143

うぉ、MSCommってホントにタイムアウトの設定が
無いですね。

API使った通信プログラムが作れない頃は、そんな
事疑問にも思わなかったですよ。
5秒ってことは無い様な気がするので、6.5秒程度
でしょうか・・・。

一応上位(?)のActiveCommではタイムアウトの設
定が可能です。(ってこんな情報役に立たないか)


我龍院忠太  2005-12-27 15:57:44  No: 129144

私の場合もAPIの場合とごっちゃになってました。
気になったのでやってみましたら、MSComm送信タイムアウトは
ひろさんのおっしゃる通りにジャスト5秒でした。
適当なレスしてごめんなさい。orz


ひでらん  2005-12-28 09:27:44  No: 129145

ひろさん、疑って申し訳ありません。
タイムアウトを5秒にする理由が私には思いつかず、
きっと65535msでタイムアウトしているのに違いないと
妄想してました。


ひろ  2006-01-10 09:58:46  No: 129146

今回の場合だと適当なところでデータを区切って送信するのが一番簡単でしょうね。バイト配列の場合のサンプルを書いておきます。

ただし、
・送信速度固定
・送信するバイト配列の添え字の下限は常に 0を想定
・分割送信が終わらないうちに次のデータを送信しようとすることはない
という前提なので少し手抜きしてありますが。

'-----------------------------------------------------------
Private Const SENDMAXSIZE As Long = 4000 '分割サイズ。送信条件から算出する事が望ましい

Private sendDataBuff() As Byte '送信データを保存しておくバッファ
Private sendPos As Long '次の送信開始位置
Private sendSize As Long 'まだMsCommに渡していないデータの量

'送信開始要求
Private Sub commSendData(b() As Byte)
    sendSize = UBound(b) + 1
    sendDataBuff = b
    sendPos = 0
    Call commSendNext()
End Sub

'続きのデータの送信
Private Sub commSendNext()
    Dim size As Long
    Dim n As Long
    Dim b() As Byte
    size = IIf(SENDMAXSIZE < sendSize, SENDMAXSIZE, sendSize)
    ReDim b(0 To size - 1)
    For n = 0 To size - 1
        b(n) = sendDataBuff(sendPos + n)
    Next
    sendPos = sendPos + size
    sendSize = sendSize - size
    MSComm1.Output = b
End Sub

'comEvSendを拾って分割の残りを送信する
Private Sub MSComm1_OnComm()
    Select Case MSComm1.CommEvent
    Case comEvReceive
        '受信処理(省略)
    Case comEvSend
        If sendSize > 0 Then
            '分割送信するべきデータがまだ残っている時は送信する
            Call commSendNext()
        Else
            '送信完了時の処理(省略)
        End If
    Case Else

    End Select
End Sub


ひろ  2006-01-10 12:49:09  No: 129147

大事なことが抜けていた・・・

MsComm1.SThreshold = 1

を初期化処理の中に書いておいて下さい。


※作成する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。







   このエントリーをはてなブックマークに追加