本示例使用设备介绍:实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com)
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Imports System.Threading
Imports System.Net.NetworkInformation
Imports System.Management
Public Class Form1
Dim PortNumber As Integer ''侦听端口号
Dim ListenerThre As Thread ''侦听线程
Dim LocalIp As String ''本地ip64
Dim ready As Boolean = False ''线程运行标识
Dim machinnos As String
Dim RemoteIPoint As IPEndPoint
Dim BeepCode As String
Dim VoiceCode As String
Public ListenerSock As Socket ''侦听socket
Delegate Sub EditUi(ByVal data0 As String, ByVal data1 As String) '线程内更新UI传送两个参数
Delegate Sub EditTC(ByVal con As Integer, ByVal data1 As String)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Control.CheckForIllegalCrossThreadCalls = False '经典解决“线程间操作无效: 从不是创建控件的线程访问它 ,尽量不要用这种方式
getIp()
ComboBox2.SelectedIndex = 0
ComboBox3.SelectedIndex = 1
ComboBox4.SelectedIndex = 16
ComboBox5.SelectedIndex = 1
StartListener() ''开始侦听
End Sub
Public Sub getIp() '获取本机所有网卡的IP
Dim Address() As System.Net.IPAddress
Dim i As Integer
Address = Dns.GetHostByName(Dns.GetHostName()).AddressList
If UBound(Address) < 0 Then
MsgBox("未能查找到本台电脑安装的网卡,暂不能启动本软件。", MsgBoxStyle.Critical + vbOKOnly, "注意")
End
Else
For i = 0 To UBound(Address)
ComboBox1.Items.Add(Address(i).ToString())
Next
ComboBox1.SelectedIndex = 0
LocalIp = ComboBox1.Text.Trim()
End If
End Sub
Private Sub StartListener()
Dim LocalPoint As IPEndPoint
PortNumber = TextBox6.Text
While Not ready
Try
LocalPoint = New IPEndPoint(IPAddress.Parse(LocalIp), PortNumber)
ListenerSock = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
ListenerSock.Bind(LocalPoint)
ListenerThre = New Thread(AddressOf ThrListener)
ListenerThre.Start()
ready = True
'ListBox1.Items.Add(LocalPoint.ToString() & "已开始侦听......")
Catch ex As Exception
ListenerSock.Close()
ready = False
MsgBox(" 有其它应用程序占用了 " & LocalPoint.ToString() & " ,请检查并关闭此应用后再打开本程序。", vbCritical + vbOKOnly, "警告")
End
End Try
End While
End Sub
Private Sub ThrListener() '侦听线程
While ready
Try
Dim bytes(1024) As Byte
Dim dataArray() As String
Dim RemotePoint As System.Net.EndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
Dim NumGet As Integer
Dim Msg As String
Dim Sendinf As String
Dim SendBuf As Byte()
Dim i As Integer
Dim DevBufferIpAddrStr As String
Dim DevBufferRemoteAddrStr As String
Dim DevBufferCardCode As String
Dim DevBufferUseTimeStr As String
Dim DevRecFramesStr As String
Dim DevBufferMachinStr As String
Dim DevBufferDatetimeStr As String
Dim DevBufferCardidStr As String
Dim DevBufferUseMoneryStr As String
Dim DevBufferReaderStr As String
Dim DevBufferDoorNoStr As String
Dim DevBufferDelayStr As String
Dim DevBufferPasswPropStr As String
Dim DevBufferPassWStr As String
Dim DevBufferStaryStr As String
Dim DevBufferRecordAddStr As String
Dim DevBufferAllNoStr As String
Dim DevBufferFunctionStr1 As String
Dim DevBufferFunctionStr2 As String
Dim DevBufferSerialNumStr As String
Dim DevBufferInputKeyStr As String
Dim DevBufferCommandStr As String
Dim DevBufferQrcodeInfStr As String
Dim DevBufferStateStr As String
Dim DevBufferRandomCode As String
Dim DevBufferSwitchStr As String
Dim DevBufferFireStr As String
NumGet = ListenerSock.ReceiveFrom(bytes, RemotePoint)
Msg = Encoding.GetEncoding(936).GetString(bytes, 0, NumGet)
'Msg = Encoding.UTF8.GetString(bytes, 0, NumGet) '读取中文wifi名称时,需用utf8解码
Me.Invoke(New EditUi(AddressOf EditUiNow), Now() & (" FromIP:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:", Msg) '用Invoke跨线程更新UI
Me.Invoke(New EditTC(AddressOf EditTCNow), 3, Convert.ToString(RemotePoint)) '用Invoke跨线程更新UI
dataArray = Split(Convert.ToString(Msg), ",")
Select Case dataArray(0)
Case "101" '接收到 1、终端开机时向电脑发送的开机信息, 2、电脑发送002查询设备时间所返回的信息
DevRecFramesStr = dataArray(1) '包序列号
DevBufferIpAddrStr = dataArray(2) '终端IP
DevBufferRemoteAddrStr = dataArray(3) '远程电脑指机IP
DevBufferMachinStr = dataArray(4) '机号
DevBufferDatetimeStr = dataArray(5) '日期时间*/
If dataArray.Length > 6 Then '2018年以后的设备有唯一硬件序号*/
DevBufferSerialNumStr = dataArray(6)
End If
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Dim SystemTimeStr As String = String.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now)
If DevBufferDatetimeStr.Substring(0, 16) <> SystemTimeStr.Substring(0, 16) Then
Sendinf = "003," & DevRecFramesStr & "," & SystemTimeStr
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
End If
Me.Invoke(New EditTC(AddressOf EditTCNow), 1, DevBufferDatetimeStr) '用Invoke跨线程更新UI
Case "150" '接收到实时考勤门禁机刷卡数据
DevRecFramesStr = dataArray(1) '包序列号
DevBufferIpAddrStr = dataArray(2) '终端IP
DevBufferRemoteAddrStr = dataArray(3) '远程电脑指机IP
DevBufferMachinStr = dataArray(4) '机号
DevBufferCardidStr = dataArray(5) '卡号
DevBufferReaderStr = dataArray(6) '消费金额*/
DevBufferDoorNoStr = dataArray(7) '门或继电器号*/
DevBufferDelayStr = dataArray(8) '门磁未关秒数,0表示已关*/
DevBufferPasswPropStr = dataArray(9) '密码属性(0密码无效,1刷卡后按密码,2补签密码,3开门密码,4防迫胁密码)*/
DevBufferPassWStr = dataArray(10) '密码(最多8位数字)*/
DevBufferUseTimeStr = dataArray(11) '消费时间*/
If dataArray.Length > 12 Then
DevBufferSerialNumStr = dataArray(12) '2018年以后的设备有唯一硬件序号
End If
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
'此处加入业务对数据库的查、增、删、减操作
'用050指令返回开门成功,051指令返回开门失败,正式系统开发时要有重发机制
Select Case VoiceCode
Case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" '发送禁止开门的指令"
Sendinf = "051," & DevBufferMachinStr & "," & DevBufferCardidStr & "," & TextBox5.Text.Trim() & "," & Format(NumericUpDown2.Value, "0") & "," & BeepCode & "," & VoiceCode
Case Else '发送开门指令
Sendinf = "050," & DevBufferMachinStr & "," & DevBufferCardidStr & "," & TextBox5.Text.Trim() & "," & Format(NumericUpDown2.Value, "0") & "," & BeepCode & "," & VoiceCode & "," & DevBufferReaderStr & "," & DevBufferDoorNoStr & "," & Format(NumericUpDown1.Value, "0") & "," & Format(NumericUpDown2.Value, "0")
End Select
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Case "151" '发送按钮开门申请信息
DevRecFramesStr = dataArray(1) '包序列号
DevBufferIpAddrStr = dataArray(2) '终端IP
DevBufferRemoteAddrStr = dataArray(3) '远程电脑指机IP
DevBufferMachinStr = dataArray(4) '机号
DevBufferInputKeyStr = dataArray(5) '&&按钮号
DevBufferReaderStr = dataArray(6) '&&对应的门或继电器号
DevBufferDelayStr = dataArray(7) '&&门磁未关秒数(0门已关)
DevBufferUseTimeStr = dataArray(8) '&&刷卡时间
If UBound(dataArray) >= 9 Then DevBufferSerialNumStr = dataArray(9) Else DevBufferSerialNumStr = "" '唯一硬件序号
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Select Case VoiceCode
Case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" '发送禁止开门的指令"
Sendinf = "051," & DevBufferMachinStr & "," & DevBufferInputKeyStr & "," & TextBox5.Text.Trim() & "," & Format(NumericUpDown2.Value, "0") & "," & BeepCode & "," & VoiceCode
Case Else '发送开门指令
Sendinf = "050," & DevBufferMachinStr & "," & DevBufferInputKeyStr & "," & TextBox5.Text.Trim() & "," & Format(NumericUpDown2.Value, "0") & "," & BeepCode & "," & VoiceCode & "," & DevBufferInputKeyStr & "," & DevBufferReaderStr & "," & Format(NumericUpDown1.Value, "0") & "," & Format(NumericUpDown2.Value, "0")
End Select
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Case "152" '门磁报警信息
DevRecFramesStr = dataArray(1) ' &&包序列号
DevBufferIpAddrStr = dataArray(2) ' &&终端IP
DevBufferRemoteAddrStr = dataArray(3) '&&远程电脑指机IP
DevBufferMachinStr = dataArray(4) '&&机号
DevBufferInputKeyStr = dataArray(5) '&&门磁号
DevBufferReaderStr = dataArray(6) '&&对应的门或继电器号
DevBufferDelayStr = dataArray(7) '&&门磁未关秒数(0门已关)
DevBufferUseTimeStr = dataArray(8) '&&刷卡时间
If UBound(dataArray) >= 9 Then DevBufferSerialNumStr = dataArray(9) Else DevBufferSerialNumStr = "" '唯一硬件序号
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Case "153" '返回查询设备状态的053指令
DevRecFramesStr = dataArray(1) ' &&包序列号
DevBufferIpAddrStr = dataArray(2) ' &&终端IP
DevBufferRemoteAddrStr = dataArray(3) '&&远程电脑指机IP
DevBufferMachinStr = dataArray(4) '&&机号
DevBufferInputKeyStr = dataArray(5) '&&继电器号
DevBufferReaderStr = dataArray(6) '&&继电器状态
DevBufferDelayStr = dataArray(7) '&&门磁未关秒数(0门已关)
DevBufferStateStr = dataArray(8) '&&门磁报警状态
If UBound(dataArray) >= 9 Then DevBufferSerialNumStr = dataArray(9) Else DevBufferSerialNumStr = "" '唯一硬件序号
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
Msg = "继电器号:" & DevBufferInputKeyStr & ",继电器状态:" & DevBufferReaderStr & ",门磁未关秒数:" & DevBufferDelayStr & ",门磁报警状态:" & DevBufferStateStr
Me.Invoke(New EditTC(AddressOf EditTCNow), 9, Msg)
Case "154" '接收到实时考勤门禁机卡离开感应区
DevRecFramesStr = dataArray(1) '包序列号
DevBufferIpAddrStr = dataArray(2) '终端IP
DevBufferRemoteAddrStr = dataArray(3) '远程电脑指机IP
DevBufferMachinStr = dataArray(4) '机号
DevBufferCardidStr = dataArray(5) '卡号
DevBufferSerialNumStr = dataArray(6)
Case "155" '&&门禁脱网记录发送----
DevRecFramesStr = dataArray(1) ' &&包序列号
DevBufferIpAddrStr = dataArray(2) ' &&终端IP
DevBufferRemoteAddrStr = dataArray(3) '&&远程电脑指机IP
DevBufferMachinStr = dataArray(4) '&&机号
DevBufferCardidStr = dataArray(5) '&&卡号
DevBufferReaderStr = dataArray(6) '&&读头
DevBufferDoorNoStr = dataArray(7) '&&门或继电器号
DevBufferPasswPropStr = dataArray(8) '&&密码属性(0密码无效,1刷卡后按密码,2补签密码,3开门密码,4防迫胁密码)
DevBufferUseTimeStr = dataArray(9) '&&刷卡时间
DevBufferStaryStr = dataArray(10) '&&状态 0扣费 1计次
DevBufferRecordAddStr = dataArray(11) '&&记录地址标识
DevBufferAllNoStr = dataArray(12) '&&总计录数
If UBound(dataArray) = 13 Then DevBufferSerialNumStr = dataArray(13) Else DevBufferSerialNumStr = "" '唯一硬件序号
Sendinf = "001," + DevRecFramesStr '向设备发此数据表示已收到信息,否则设备会连续发三次
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
If Not IsDateTime(DevBufferUseTimeStr) Then '记录的刷卡时间非法,表示此记录有问题(测试时的其它数据)
DevBufferUseTimeStr = "9999-99-99 99:99:99"
End If
'这里对脱网记录进行处理
If CheckBox3.Checked Then '选择清除已上传的记录驱使用设备继续上传剩下的记录
Sendinf = "055," + DevBufferMachinStr + "," + DevBufferCardidStr + "," + DevBufferUseTimeStr + "," + DevBufferRecordAddStr '&&清除设备内当前这条记录,设备才会传下一条记录
SendBuf = Encoding.GetEncoding(936).GetBytes(Sendinf)
ListenerSock.SendTo(SendBuf, SendBuf.Length, SocketFlags.None, RemotePoint)
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, Now() & (" SendTo:" & Convert.ToString(RemotePoint) + " ").Substring(0, 30) & "Data:" & Sendinf)
End If
Case "158" '响应电脑远程开门的058指令
DevRecFramesStr = dataArray(1) ' &&包序列号
DevBufferIpAddrStr = dataArray(2) ' &&终端IP
DevBufferRemoteAddrStr = dataArray(3) '&&远程电脑指机IP
DevBufferMachinStr = dataArray(4) '&&机号
DevBufferStaryStr = dataArray(5) '&&0开门成功,1开门密码认证失败,2开门密码认证失败超过6次,需等待一段时间后再能再次接收058指令(防暴力破解),3 不允许此时间段开门
DevBufferRandomCode = dataArray(6) '&&动态随机码(8位十六进制)
Me.Invoke(New EditTC(AddressOf EditTCNow), 10, DevBufferRandomCode)
Msg = ""
Select Case DevBufferStaryStr
Case "0"
Msg = "IP:" & DevBufferIpAddrStr & " 开门成功"
Case "1"
Msg = "IP:" & DevBufferIpAddrStr & " 开门密码认证失败!"
Case "2"
Msg = "IP:" & DevBufferIpAddrStr & " 开门密码认证失败超过6次,需等待一段时间后再能再次接收058指令(防暴力破解)"
Case "3"
Msg = "IP:" & DevBufferIpAddrStr & " 不允许此时间段开门"
End Select
Me.Invoke(New EditTC(AddressOf EditTCNow), 9, Msg)
Me.Invoke(New EditTC(AddressOf EditTCNow), 10, DevBufferRandomCode)
Case "159" '&&心跳信息
DevRecFramesStr = dataArray(1) ' &&包序列号
DevBufferIpAddrStr = dataArray(2) ' &&终端IP
DevBufferRemoteAddrStr = dataArray(3) '&&远程电脑指机IP
DevBufferMachinStr = dataArray(4) '&&机号
DevBufferQrcodeInfStr = dataArray(5) '&&信息类型
DevBufferSwitchStr = dataArray(6) '继电器状态(bit0为第1门bit1为第2门)
DevBufferFireStr = dataArray(7) '消防输入状态
DevBufferRandomCode = dataArray(8) '&&动态随机码(8位十六进制)
DevBufferDatetimeStr = dataArray(9) '日期时间
DevBufferSerialNumStr = dataArray(10) '设备硬件号
Me.Invoke(New EditTC(AddressOf EditTCNow), 10, DevBufferRandomCode)
End Select
Catch ex As Exception
Me.Invoke(New EditTC(AddressOf EditTCNow), 2, "ERROR:" & vbCrLf & ex.GetHashCode & ex.Message & vbCrLf)
End Try
End While
End Sub