2016-05-31 127 views
2

幾年前,我做了一個軟件,使用VB6作爲TCP服務器,接收來自客戶端的多個連接。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 

一切工作正常,但現在連接的數量有所增加(夫婦幾十每秒),所以軟件開始得到(因爲DoEventsOut of stack space例外。我知道在很多情況下,DoEvents是邪惡的,但如果我刪除它,應用程序UI將不會響應(因爲線程負載過重),並且某些數據可能無法傳遞。

所以,我的問題是:有沒有人有一個想法,如何解決這個問題/不使用DoEvents


注:我知道VB6真的不支持多線程和可能是一個PITA用於這種情況。我實際上打算升級軟件並使用.Net重新創建它,但這需要一些時間。這就是爲什麼我需要在VB6中解決這個問題,因爲現在該軟件是用VB6編寫的。

+0

我真的不明白爲什麼doevents應該在dataarrival處理程序的最後一行,我會把它放在繁重的循環中。從技術上講,doevents做了一個簡單的「yield」,因此,out of stack錯誤可能會有另外一個來源,比如sdata的大小,我會把它放在外面的數組中,並且使用連接索引來訪問它,我完全理解這很髒,但應該幫助節省一些堆。 – Gar

+0

1-我在'DataArrival'處理程序中放置了'DoEvents',因爲它觸發了'Winsock.SendData',並且「如果我刪除它,應用程序UI將不會響應(因爲線程負載過重)並且某些數據可能會不被交付「。 2-「重載」是什麼意思? 3-當出現「堆棧空間不足」錯誤時,堆棧將充滿'sckAccept_DataArrival'事件。我假設這是因爲'DoEvents'允許再次觸發事件(其中包含另一個'DoEvents',等等)。 4'sData'的大小非常小(40-100字節) –

+0

我完全理解爲什麼你使用了doevents,我只是沒有看到它的末尾,我用來「doevents」內循環,以便循環不會鎖定應用程序。即使數據量很小,您也只能獲得一些空間,並且不會有任何問題。我也瞭解,導致你的問題的原因是堆棧中未回答的tcp查詢(因爲它們的處理程序正在爲它們查詢數據庫)。 – Gar

回答

1

嗯,我設法弄清楚這個問題,並解決了它。

簡短的回答

不要使用DoEvents。有些數據將不會被髮表?那麼,請僅在SendComplete事件中關閉連接。


長的答案

第一件事,第一:

爲什麼我首先使用DoEvents?因爲發送的一些消息沒有被傳送。在互聯網上的很多文章/問題建議在Socket.SendData之後使用DoEvents以保證數據到達接收器。

我深入瞭解了這一點,試圖找出爲什麼郵件沒有交付。我發現,在發送消息後關閉連接時纔會出現此問題:

Socket.SendData "Message" 
' 
' 
Socket.Close 

所以,我乾脆搬到封閉到SendComplete事件的連接線,取出DoEvents一句話 - 由於我不知道需要它了,問題就沒了:)

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

我希望這可以幫助有同樣問題的人。