DataArrivalイベントを利用して複数クライアントからの受信データ(256バイト固定長)を利用したいのですが、クライアントが一斉にデータを送信すると、受信データをうまく整理することができません。(混在する場合がある)
よいアドバイスがあれば教えてください。
なお、現在
Private Sub tcpServer_DataArrival(Index as Integer, Byval bytesTotal As Long)
Dim tmpBuff As String
tcpServer(Index).GetData tmpBuff, vbString, bytesTotal
mRecLen(Index) = mRecLen(Index) + bytesTotal
mRecvBuff(Index) = mRecvBuff(Index) & tmpBuff
If (mRecLen(Index) >= 256) then
--- 処理 ---
End If
:
:
といった感じです。
追加ですが「mRecvBuff(Index)に、複数クライアントからの受信データが混在してしまいます。
このソースだけでは現象が再現不可能なので、恐らく原因は他にあるのではないでしょうか。
私も、Winsockコントロールを使用して複数クライアントからの接続を行う
プログラムを作ったことがありますが、一斉に送信しても一つ一つの処理が
遅くなるだけで混在することはありませんでした。
「。。。」さん。早速の情報ありがとうございます。
私の情報が皆無でまことに申し訳ありません。
まず、環境ですが、OS:Windows2000 アプリケーション:VB(6.0)です。
プログラムの流れを簡単に申し上げますと、、、
Private Sub Form_Load()
ReDim mRecLen(mMaxConnections)
ReDim mRecvBuff(mMaxConnections)
' Winsockコントロール配列を作成
For idx = 1 To mMaxConnections
Load tcpServer(idx)
tcpServer(idx).LocalPort = 0
mRecLen(idx) = 0 ' 受信レコード長を初期化
mRecvBuff(idx) = "" ' 受信データの初期化
Next
' リスニングコントロールの初期化
tcpServer(0).LocalPort = cCONNECT_PORT
tcpServer(0).Listen
End Sub
Private Sub tcpServer_ConnectionRequest
(Index As Integer, ByVal requestID As Long)
Dim idx As Integer
If (Index = 0) Then
For idx = 1 To mMaxConnections
If (tcpServer(idx).State = sckClosed) Then
tcpServer(idx).Accept requestID
Exit For
End If
Next
End If
End Sub
といった感じで、接続を待ちうけ、初回に書いた内容でデータを取得
しております。
通常の通信ではデータの混在は無いのですが、約7台以上のクライア
ントが一斉にデータ送った場合に、稀(数百回に1度程度)ですが、
データ混在が発生します。
(PHSを利用した基地局からのデータ受信です)
これでも未だ情報不足とは思いますが、何かヒントがあれば、教えて
ください。
どうぞ宜しくお願いします。
mRecLen(Index)の初期化はどこでやっているのでしょう?
単に前の接続のデータが残っているとかではないですか?
「。。。」さん。お返事ありがとうございます。
早速なのですが、最初に見ていただいた「DataArrival」の中で、mRecLen(Index)の初期化を入れてあります。
下のような感じです。
Private Sub tcpServer_DataArrival(Index as Integer, Byval bytesTotal As Long)
Dim tmpBuff As String
tcpServer(Index).GetData tmpBuff, vbString, bytesTotal
mRecLen(Index) = mRecLen(Index) + bytesTotal
mRecvBuff(Index) = mRecvBuff(Index) & tmpBuff
If (mRecLen(Index) >= 256) then
--- ↓↓処理↓↓ ---
:
:
--- ↑↑処理↑↑ ---
mRecLen(Index) = 0 '<----この部分です。
mRecvBuff(Index) = ""
End If
初期化の場所が不適切なのでしょうか。。。?
素人質問で申し訳ないのですが、教えてください。
宜しくお願いします。
クライアントとサーバーの通信の仕様はどうなっているのでしょう?
クライアントは1回の接続で256バイト送信すると接続を切断するのですか?
続けて次のデータを送信したりはしないのですか?
つまり、上記初期化方法では前回のデータと今回のデータの一部を受信した
時にDataArrivalイベントが発生すると今回のデータの一部が初期化されて
しまう可能性があります。
たけさん。問題解決のご協力ありがとうございます。
<クライアントとサーバーの通信の仕様はどうなっているのでしょう?
<クライアントは1回の接続で256バイト送信すると接続を切断するのですか?
<続けて次のデータを送信したりはしないのですか?
上記質問についてですが、クライアントはデータ送信後、サーバーが返すデータの受信を行った後に、接続を切断しております。
また、クライアントが送信するデータは256バイト固定にしております。
しかし、一点気になることが。。
--- ↓↓処理↓↓ ---
:
:
--- ↑↑処理↑↑ ---
の部分ですが、
Call subXXXX(mRecvBuff(Index))
tcpServer(Index).SendData mRecvBuff(Index)
DoEvents
のようなことをしており、プロシージャで使用する引数と戻り値に同じものを利用しております。
この処理は4秒近くかかることもあり、これが原因で受信データと送信データ混在しているように思えます。(気のせいでしょうか???)
取り合えず、プロシージャ利用の際の引数と戻り値を切り分け、mRecvBuff(Index) の初期化をプロシージャ呼び出し前に行って症状がでないか確認してみます。
・・・実はテストできるのが今週3日になりますので・・・。
もし、ご意見等がございましたら、もう少しご教授願います。
宜しくお願いします。
横スマソ
ムチャクチャ勘だけど、DoEventsが少し怪しい気がする…
後、一応確認なんですけど、
複数のクライアントが送ったものが混ざっている様に見えるだけ、
というわけではないですよね?
※最近Winsockコントロールの挙動が怪しすぎるので、
自分だけのライブラリを作り始めたガッでした。
…もしかしたらWinsockコントロールのバグだったりして…
ぃぁ…出来ている人がいるので、それはないか(orz
ガッさん。アドバイスありがとうございます。
<複数のクライアントが送ったものが混ざっている様に見えるだけ、
<というわけではないですよね?
ですが、改めて送受信データを解析したところ、複数クライアントのデータ混在ではなく、自分自身の送受信データ混在が発生していると断定できました。
したがって、やはり使用変数の初期化辺りに原因があるように思われます。
3日(木)に確認したいと思います。
しかし・・・。Winsock コントロールのバグ・・・あるのでしょうか・・・。(5.0のsp5ですが・・・)情報収集に努めてみます。
どうもありがとうございました。
その他にも、よろしければ色々とアドバイスお願いします。
宜しくお願いします。
すみません。Winsockですが、間違えていたので訂正します。
5.0 (SP5) --> ×
6.0 (SP5) --> ○
です。
2つ気になる点があります。
1、グローバルで宣言した文字列を、あちこちで使いまわすと
思わぬバグが発生する。
2、次から次と割り込みがかかるサブルーティンで時間のかかる
処理をすると、思わぬ不具合が発生する。
ここの2つの問題を同時に解決するには、Timerを使う手がありますが、
私ならWinsockコントロールと同じIndex番号を持つTextBoxを非表示で用意し、
If (mRecLen(Index) >= 256) then
Text1(Index) = mRecvBuff(idx)
mRecvBuff(idx) = 0
End If
とやり
テキストボックスのチェンジイベントの中で、
Private Sub Text1_Change(Index As Integer)
--- ↓↓処理↓↓ ---
:
:
--- ↑↑処理↑↑ ---
End Sub
とやる。
こうするとmRecvBuff(Index)はローカルで宣言すれば良く、
Private Sub tcpServer_DataArrival(・・・・)
の割り込みルーチンもデーターを受け取ってすぐに開放できる。
皆様。色々とアドバイスありがとうございました。
本日テストした結果、前回よりも多いアクセスにも関わらず、症状が
全くでなくなったので、うまいこと改善できたと思われます。
改善した内容は、送受信で利用していた「mRecvBuff(Index)」これを
データ受信時のみ利用し、「>=256」True で初期化しました。
また、「処理」のところでも、引数と戻り値を別で定義しました。
全く素人バグ&対応といった感じでお恥ずかしいのですが、「ふーん」
程度に受け止めてください。
しかしながら、皆様のアドバイスは今後のコーディング力アップに
役立てていきたいと思います。
本当にありがとうございました。
ツイート | ![]() |