'Imports System.Net
'Imports System.Net.Sockets

'Public Class WebService
'    Implements IDisposable

'    Enum PacketDataEnum
'        Head
'        SerialNumber
'        ParamLength
'        CheckValue
'        Command
'        Param
'    End Enum

'    <Flags()>
'    Enum PacketSendCmdEnum
'        Heartbeat = &H1

'    End Enum

'    <Flags()>
'    Enum PacketReceiveCmdEnum
'        Heartbeat = &HA1

'    End Enum

'    Private _localPublicIp As String

'    Private ReadOnly _udpClient As UdpClient

'    Private _sendPacketSn As Integer

'    Private ReadOnly _hostName As String

'    Private ReadOnly _remotePort As Integer

'    Private _online As Boolean

'    Private _failCount As Integer

'    Sub New(hostName As String, port As Integer)
'        _hostName = hostName
'        _remotePort = port

'        _udpClient = New UdpClient()
'        _sendPacketSn = 0

'        RetryCount = 2
'        RetryInterval = 5
'        WaitRelayTimeout = 2000

'        _online = False
'        _localPublicIp = String.Empty
'    End Sub


'    Public ReadOnly Property LocalPublicIp() As String
'        Get
'            Return _localPublicIp
'        End Get
'    End Property


'    Public ReadOnly Property Online() As Boolean
'        Get
'            Return _online
'        End Get
'    End Property

'    ''' <summary>
'    ''' 重试次数，不包含第一次发送次数，默认值2
'    ''' </summary>
'    ''' <returns></returns>
'    Public Property RetryCount() As Integer

'    ''' <summary>
'    '''  重试间隔,单位ms，默认5ms
'    ''' </summary>
'    ''' <returns></returns>
'    Public Property RetryInterval() As Integer
                   
'    ''' <summary>
'    ''' 等待接收超时时间,单位ms,默认2000ms
'    ''' </summary>
'    ''' <returns></returns>
'    Public Property WaitRelayTimeout() As Integer


'    Public Sub SendHeartbeatPacket(serviceIndex As Integer)
'        Dim sendByte() As Byte = FillPacket(CByte(PacketSendCmdEnum.Heartbeat), BitConverter.GetBytes(serviceIndex))

'        Send(sendByte)
'    End Sub


'    Public Function FillPacket(cmd As Byte, param() As Byte) As Byte()
'        Dim result(PacketDataEnum.Command + param.Length) As Byte
'        result(PacketDataEnum.Head) = &HAA
'        result(PacketDataEnum.SerialNumber) = CByte(_sendPacketSn)
'        result(PacketDataEnum.ParamLength) = CByte(param.Length)
'        result(PacketDataEnum.CheckValue) = &H0
'        result(PacketDataEnum.Command) = cmd

'        Array.Copy(param, 0, result, PacketDataEnum.Param, param.Length)
'        result(PacketDataEnum.CheckValue) = GetCheckSum(result)

'        Return result
'    End Function


'    Public Sub Send(packet() As Byte)
'        Static receivedReply As Boolean = False
'        Static waitReplyStartTime As DateTime

'        receivedReply = False
'        For i As Integer = 0 To RetryCount
'            _udpClient.Send(packet, packet.Length, _hostName, _remotePort)
'            waitReplyStartTime = Now


'            While receivedReply = False AndAlso (Now - waitReplyStartTime).TotalMilliseconds < WaitRelayTimeout
'                If _udpClient.Available <= 0 Then
'                    Threading.Thread.Sleep(50)
'                    Continue While
'                End If

'                Dim ep As IPEndPoint = Nothing
'                Dim receiveByte() As Byte = _udpClient.Receive(ep)

'                '校验
'                Try
'                    CheckPacket(receiveByte)
'                Catch ex As Exception
'                    ApplicationLog.WriteErrorLog($"Check Receive Data Error:{ex.Message}")
'                    Continue While
'                End Try


'                '处理
'                Try
'                    DealPacket(receiveByte)
'                Catch ex As Exception
'                    ApplicationLog.WriteErrorLog($"Deal Receive Data Error:{ex.Message}")
'                    Continue While
'                End Try

'                receivedReply = True
'            End While

'            If receivedReply Then
'                Exit For
'            End If

'            Threading.Thread.Sleep(RetryInterval)
'        Next

'        If _sendPacketSn + 1 >= 256 Then
'            _sendPacketSn = 0
'        Else
'            _sendPacketSn += 1
'        End If

'        If receivedReply = False Then
'            _failCount += 1
'            If _failCount >= 3 Then
'                _failCount = 3
'                _online = False
'            End If
'        Else
'            _failCount = 0
'            _online = True
'        End If
'    End Sub


'    Private Sub CheckPacket(packet() As Byte)
'        If packet(PacketDataEnum.Head) <> &HAA Then
'            Throw New Exception($"Invalid Packet Head!Src:{packet(PacketDataEnum.Head)} Dest:{&HAA}")
'        End If

'        If packet(PacketDataEnum.SerialNumber) <> _sendPacketSn Then
'            Throw New Exception($"Invalid Packet Sn!Src: {packet(PacketDataEnum.SerialNumber)} Dest:{_sendPacketSn}")
'        End If

'        Dim destLength As Integer = packet.Length - PacketDataEnum.Param
'        If packet(PacketDataEnum.ParamLength) <> destLength Then
'            Throw New Exception($"Invalid Packet Lengnt!Src:{packet(PacketDataEnum.ParamLength)} Dest:{destLength}")
'        End If

'        If GetBytesSum(packet) <> &HFF Then
'            Throw New Exception($"Invalid Packet CheckValue!Src:{BitConverter.ToString(packet)}")
'        End If

'    End Sub


'    Private Function GetCheckSum(packet() As Byte) As Byte
'        Dim result As Integer

'        For Each b As Byte In packet
'            result += b
'            result = result And &HFF
'        Next

'        Return CByte(&HFF - result)
'    End Function


'    Private Function GetBytesSum(packet() As Byte) As Byte
'        Dim result As Integer

'        For Each b As Byte In packet
'            result += b
'            result = result And &HFF
'        Next

'        Return CByte(result)
'    End Function


'    Public Sub DealPacket(packet() As Byte)
'        Select Case packet(PacketDataEnum.Command)
'            Case CByte(PacketReceiveCmdEnum.Heartbeat)
'                DealHeartbeatPacket(packet)
'            Case Else
'                Throw New Exception($"Unknown Command:{packet(PacketDataEnum.Command)}")
'        End Select

'    End Sub


'    Private Sub DealHeartbeatPacket(packet() As Byte)
'        Dim tmpIp As String
'        tmpIp = $"{packet(PacketDataEnum.Param)}.{packet(PacketDataEnum.Param + 1)}.{packet(PacketDataEnum.Param + 2)}.{packet(PacketDataEnum.Param + 3)}"

'        If String.Compare(LocalPublicIp,tmpIp) <> 0 Then
'            _localPublicIp = tmpIp
'        End If

'    End Sub

'    Public Sub Dispose() Implements IDisposable.Dispose
'        _udpClient.Dispose()

'    End Sub

'End Class
