2016-05-31 56 views
2

TCPサーバーとして動作するVB6を使用して数年前にソフトウェアを作成し、クライアントから複数の接続を受け取りました。VB6 Winsock複数のTCP接続> DoEventsの問題

ソフトウェアの基本的なアイデアは、特定のポートでリッスンし、異なるクライアントからの接続を受け入れ、データを分析する別のwinsockに各接続を渡し、DBを探し、適切なメッセージで応答し、接続を閉じます。アプリケーションの起動時に

ソケットの初期化:

For i = 1 To MaxCon  
    Load sckAccept(i) 
Next i 
sckListen.Listen 

の接続を受け入れること:ここで

は、いくつかのコードだ

Private Sub sckListen_ConnectionRequest(ByVal requestID As Long) 
    Dim aFreeSocket As Integer 
    aFreeSocket = GetFreeSocket 
    If aFreeSocket = 0 Then 
     sckAccept(0).Accept requestID 
     sckAccept(0).SendData "Server is full!" 
     sckAccept(0).Close 
    Else 
     sckAccept(aFreeSocket).Accept requestID   
End Sub 

受信データを、それを分析し、そして返信:

Private Sub sckAccept_DataArrival(Index As Integer, ByVal bytesTotal As Long) 
    Dim sData As String 
    sckAccept(Index).GetData sData 
    'Do lots of analyizing and search in DB 
    ' 
    ' 
    sckAccept(Index).SendData "Message" 
    ' 
    ' 
    DoEvents 
    sckAccept(Index).Close 
End Sub 

すべてが正常に働いていたが、現在は接続数は、(毎秒カップルの数十)増加しているので、ソフトウェアが(理由DoEventsの)Out of stack space例外を取得し始めました。

多くの場合、DoEventsが悪いですが、削除するとアプリケーションのUIが応答せず(スレッドの負荷が高いため)、一部のデータが配信されない可能性があります。

だから私の質問です:DoEventsを使用してこの問題を回避する方法のアイデアはありますか?


注:私はVB6は本当にマルチスレッドをサポートしていないとこのような状況のためにPITAであるかもしれないことを知っています。私は実際にソフトウェアをアップグレードし、.Netを使用してソフトウェアを再作成する予定ですが、それには時間がかかります。 VB6でこの問題を解決する必要があるのはこのためですが、今はVB6で書かれています。

+0

私は正直なところ、doeventsがdataarrivalハンドラの最後の行になければならないと分かりません。重いループの中に入れてしまいます。技術的には、doeventsは単純な "yield"を実行するので、スタック不足エラーはsdataのサイズのような別のソースを持つ可能性があります。外部の配列に配置し、接続インデックスを使用してアクセスします。いくつかのヒープを保存するのに役立ちます。 – Gar

+0

1 'DataArrival'ハンドラの中に' DoEvents'を入れます。なぜなら、 'Winsock.SendData'をトリガするからです。アプリケーションのUIは応答しません(スレッドの過負荷のため)。配送されない "。 2 - 「重い荷物」はどういう意味ですか? 3-スタックスペース不足エラーが発生すると、スタックは 'sckAccept_DataArrival'イベントでいっぱいになります。これは、 'DoEvents'がイベントを再度トリガーできるようにするためです(別の' DoEvents'を含むなど)。 4 - 'sData'のサイズはかなり小さいです(40-100バイト) –

+0

私はdoeventsを使った理由を完全に理解しています。私はちょうどサブの終わりまでは見ません。ループ内で" doevents "ループはアプリケーションをロックしません。そしてたとえsdataが小さくても、あなたはわずかなスペースしか得られません。私はあなたの問題を引き起こすのは、未解決のtcpクエリーが(それらのハンドラーがそれらのデータベースを照会しているので)積み重なっていることも理解しています。 – Gar

答えて

1

私は問題を把握して解決しました。

短い答え

は、一部のデータが配信されることはありません... DoEventsを使わないのでしょうか?さて、SendCompleteイベントでのみ接続を閉じてください。


長い答え

まず最初のもの:

私が最初の場所でDoEventsを使用なぜ? のメッセージの一部が配信されなかったためです。受信機へのデータ到着を保証するために、Socket.SendDataの後に、DoEventsを使用してインターネット上の多くの記事/質問が示唆されています。

メッセージが配信されない理由を理解するために、これをさらに深く掘り下げました。私は、メッセージ送信後に接続を閉じるときに、この問題が発生することが判明:だから

Socket.SendData "Message" 
' 
' 
Socket.Close 

を、私は単純に、SendCompleteイベントへの接続を閉じ行を移動し、私はしませんDoEvents文-sinceを削除しましたもう問題がなくなりました。

Private Sub sckAccept_SendComplete(Index As Integer) 
    sckAccept_Close (Index) 
End Sub 

これは、同じ問題を抱えている人に役立つことを望みます。