'Imports System.Net 'Imports System.Net.Sockets 'Public Class WebService ' Implements IDisposable ' Enum PacketDataEnum ' Head ' SerialNumber ' ParamLength ' CheckValue ' Command ' Param ' End Enum ' ' Enum PacketSendCmdEnum ' Heartbeat = &H1 ' End Enum ' ' 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 ' ''' ' ''' 重试次数,不包含第一次发送次数,默认值2 ' ''' ' ''' ' Public Property RetryCount() As Integer ' ''' ' ''' 重试间隔,单位ms,默认5ms ' ''' ' ''' ' Public Property RetryInterval() As Integer ' ''' ' ''' 等待接收超时时间,单位ms,默认2000ms ' ''' ' ''' ' 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