连接到VB6 Winsock控件的.NET TcpClient在Winsock控件关闭时不会关闭

时间:2013-05-09 20:12:20

标签: vb.net tcp vb6 vb6-migration

这个问题有点令人困惑,我一遍又一遍地尝试使用Google和Stack Overflow来寻找答案。我在VB.NET中编写了一个Windows服务,它使用TcpListener类来监听连接应用程序。这是一个相当简单的服务,只允许应用程序的多个实例将UDP数据报发送到我们的端口7000上监听的仪器。服务的原因是因为它必须在端口7001上监听来自仪器的UDP数据报,并将它们转发使用TCP连接到客户端应用程序。

无论如何,在我的问题上。当客户端应用程序是使用TcpClient连接到服务的VB.NET应用程序时,一切运行正常。当客户端应用程序关闭其TCP连接时,服务中的TcpClient不能再接收数据(这会导致异常,从而提示服务关闭并删除有问题的TcpClient)。到目前为止一切都很好。

当客户端是使用Winsock控件连接到服务的VB6应用程序时,一切都很好,直到Winsock控件关闭连接。此时,TcpClient.Connected属性仍为True,尝试读取流不会导致异常。本质上,该服务仍然认为连接是开放的。更糟糕的是,网络流中BeginReceive函数的回调函数不断被调用,因为TcpClient被假定为关闭。这会导致Process Explorer显示使用100%处理器(或核心)的服务。经过进一步调查,Process Explorer将连接状态报告为CLOSE_WAIT。

也许在TcpClient类中有另一个属性或方法,我可以检查连接是关闭还是关闭。但到目前为止我还没有找到它。这是代码的副本供大家查看。也许你可以看到我错过了什么。感谢您花时间阅读本文。

' Receives the TCP packet from the clients, processes them and forwards them on as requested.
Private Sub ReceiveTcpPacketCallback(ByVal AsyncResult As System.IAsyncResult)
    ' Retrieve the asynchronous state for the callback.
    Dim AsyncState As TcpAsyncState = CType(AsyncResult.AsyncState, TcpAsyncState)

    ' Get the TCP client associated with this state.
    Dim TcpClient As System.Net.Sockets.TcpClient = AsyncState.TcpClient

    Try
        If TcpClient.Connected Then
            Dim CommandData As String

            ' Get the network stream associated with the TCP client that sent the packet.
            Dim NetworkStream As System.Net.Sockets.NetworkStream = TcpClient.GetStream

            ' Sync lock the receive buffer to ensure that no other threads are touching it.
            SyncLock m_pReceiveBuffer
                ' End the read to retrieve the data into the locked buffer.
                Dim DataLength As Integer = NetworkStream.EndRead(AsyncResult)

                ' Convert the bytes retrieved into a string using ASCII encoding.
                CommandData = System.Text.Encoding.ASCII.GetString(m_pReceiveBuffer, 0, DataLength)
            End SyncLock

            ' Process the command data that was sent from the TCP client and process the command if complete.
            If AsyncState.ProcessCommandData(CommandData) Then ProcessCommandInformation(AsyncState)

            ' Continue listening for more commands from the client.
            NetworkStream.BeginRead(m_pReceiveBuffer, 0, m_pReceiveBuffer.Length, AddressOf ReceiveTcpPacketCallback, AsyncState)
        Else
            ' Attempt to close the TCP client and remove it from the list.
            TcpClient.Close()
            If m_pTcpClients.Contains(TcpClient) Then m_pTcpClients.Remove(TcpClient)
        End If
    Catch ex As Exception
        Dim Message As New System.Text.StringBuilder

        ' If an exception occurs, assemble the message to write to the event log.
        Message.Append(Date.Now.ToString).Append(","c).Append("ReceiveTcpPacketCallback Exception,")
        Message.Append("Error Receiving Command From TCP Client,")
        Message.Append(ex.Source).Append(","c).Append(ex.Message)

        ' Write the message to the event log.
        Me.EventLog.WriteEntry(Message.ToString)

        ' Attempt to close the TCP client and remove it from the list.
        TcpClient.Close()
        If m_pTcpClients.Contains(TcpClient) Then m_pTcpClients.Remove(TcpClient)
    End Try
End Sub

0 个答案:

没有答案