c# VB.NET TcpClientHelper带掉线事件

Imports System.ComponentModel
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class TcpClientHelper
    Inherits Component
    Private m_csTcpClient As TcpClient
    Public m_csNetworkStream As NetworkStream
    Public m_strIP As String = "127.0.0.1"
    Public m_intPort As UInt16 = 8080
    Private readBytes() As Byte
    Private tcpClientLock As New Object()
    Public Property m_csIPEndPoint As IPEndPoint = Nothing '服务器IP和端口
    Public Property ISBreaklineReconnection As Boolean = False
    Public Event RecvMsgEvent(strMSG As String)
    Public Event DisconnectEvent(strMSG As String)
    Public Event LogMsg(csException As Exception)
    Private m_bolISActive As Boolean = False
    Dim csBackgroundWorker As New System.ComponentModel.BackgroundWorker
    Public Sub New()
        AddHandler csBackgroundWorker.DoWork, AddressOf WorkerDoWork
    End Sub

    Public ReadOnly Property ISActive() As Boolean
        Get
            Return m_bolISActive
        End Get
    End Property

    ''' <summary>
    ''' 一直连接直到成功
    ''' </summary>
    Public Sub ReConnect()
        If csBackgroundWorker.IsBusy = False AndAlso m_bolISActive = False Then
            csBackgroundWorker.RunWorkerAsync()
        End If
    End Sub
    Private Sub WorkerDoWork(sender As Object, e As DoWorkEventArgs)
        Try
            Dim isReconnect As Boolean = True
            Dim tryReconnectTimes As Integer = 0
            Dim m_csWaitHandle As New ManualResetEvent(False)
            While isReconnect AndAlso csBackgroundWorker.CancellationPending = False
                Try
                    If Connect() = False Then
                        isReconnect = True
                    Else
                        isReconnect = False
                    End If
                Catch ex As Exception
                    RaiseEvent LogMsg(ex)
                End Try
                m_csWaitHandle.WaitOne(1000)
            End While
        Catch ex As Exception
            RaiseEvent LogMsg(ex)
        End Try
    End Sub

    ''' <summary>
    ''' 一次连接
    ''' </summary>
    ''' <returns></returns>
    Public Function Connect() As Boolean
        If m_csIPEndPoint Is Nothing Then
            Throw New Exception("未设置IP地址和端口号!")
            Return False
        End If
        Try
            m_csTcpClient = New TcpClient(AddressFamily.InterNetwork)
            m_csTcpClient.ReceiveTimeout = 1000
            m_csTcpClient.SendTimeout = 1000
            readBytes = New Byte(m_csTcpClient.ReceiveBufferSize - 1) {}
            m_csTcpClient.Connect(m_csIPEndPoint)
            m_csTcpClient.Client.IOControl(IOControlCode.KeepAliveValues, KeepAlive, Nothing)
            m_csNetworkStream = m_csTcpClient.GetStream()
            m_csNetworkStream.BeginRead(readBytes, 0, readBytes.Length, AddressOf EndRead, Nothing)
            m_bolISActive = True
            RaiseEvent LogMsg(New Exception("连接成功")Catch ex As Exception
            Throw ex
        End Try
        Return True
    End Function
    ''' <summary>
    ''' 断开连接
    ''' </summary>
    Public Sub DisConnect()
        Dispose(True)
    End Sub
    ''' <summary>
    ''' KeepAlive函数参数说明
    ''' </summary>
    ''' <param name="keepAliveTime">开始首次KeepAlive探测前的TCP空闭时间</param>
    ''' <param name="keepAliveInterval">两次KeepAlive探测间的时间间隔</param>
    ''' <param name="onOff">是否开启KeepAlive,默认开启</param>
    ''' <returns></returns>
    Private Function KeepAlive(Optional ByVal keepAliveTime As Integer = 1000,
                             Optional ByVal keepAliveInterval As Integer = 100,
                               Optional ByVal onOff As Integer = 1) As Byte()
        Dim buffer(11) As Byte
        BitConverter.GetBytes(onOff).CopyTo(buffer, 0)
        BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4)
        BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8)
        Return buffer
    End Function


    ''' <summary>
    ''' 在建立连接的情况下发送消息
    ''' </summary>
    ''' <param name="msg"></param>
    ''' <returns></returns>
    Public Function SendMsg(ByVal msg As String) As Boolean
        If m_bolISActive = False Then
            Return False
        End If
        Dim result As Boolean = False
        Try
            Dim buff() As Byte = Encoding.Default.GetBytes(msg)
            m_csNetworkStream.Write(buff, 0, buff.Length)
            result = True
        Catch
            Throw
        End Try
        Return result
    End Function
    ''' <summary>
    ''' 有互斥资源
    ''' 接收数据,远程连接断开,远程程序关闭,本地连接断开,都会按顺序调用进来;因为连接关闭后不再调用BeginRead
    ''' </summary>
    ''' <param name="ar"></param>
    Private Sub EndRead(ByVal ar As IAsyncResult)
        SyncLock tcpClientLock
            If m_bolISActive Then '如果本地主动断开就不会进入
                Try
                    Dim count As Integer = m_csNetworkStream.EndRead(ar)
                    If count > 0 Then
                        Dim recvStr As String = Encoding.Default.GetString(readBytes, 0, count)
                        RaiseEvent RecvMsgEvent(recvStr)
                        readBytes = New Byte(m_csTcpClient.ReceiveBufferSize - 1) {}
                        m_csNetworkStream.BeginRead(readBytes, 0, readBytes.Length, AddressOf EndRead, Nothing)
                    Else '远程客户端主动断开
                        LocalClientClose("TcpServer关闭")
                    End If
                Catch ex As Exception '网线断开的时候会触发此事件
                    LocalClientClose("网线断开")
                End Try
            End If
        End SyncLock
    End Sub
    ''' <summary>
    ''' 远程连接断开后(点关闭断开,程序退出断开)本地连接处理
    ''' </summary>
    Private Sub LocalClientClose(ByVal strType As String)
        m_bolISActive = False
        DisposeEx()
        Dim param As String = strType & " " & m_strIP & " " & m_intPort
        RaiseEvent DisconnectEvent(param)
        If ISBreaklineReconnection Then
            ReConnect()
        End If
    End Sub
    Protected Overrides Sub Dispose(disposing As Boolean)
        SyncLock tcpClientLock
            If m_bolISActive Then
                m_bolISActive = False
                DisposeEx()
                RaiseEvent DisconnectEvent("主动退出")
            End If
        End SyncLock
    End Sub
    ''' <summary>
    ''' 由Dispose和LocalClientClose调用
    ''' </summary>
    Private Sub DisposeEx()
        If m_csNetworkStream IsNot Nothing Then
            m_csNetworkStream.Dispose()
            m_csNetworkStream = Nothing
        End If
        If m_csTcpClient IsNot Nothing Then
            m_csTcpClient.Close()
            m_csTcpClient = Nothing
        End If
    End Sub
End Class


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值