2016-05-31 117 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 

我希望这可以帮助有同样问题的人。