本示例使用设备:实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Management;
namespace UdpPostReaderDemoCSharp
{
public partial class Form1 : Form
{
Form3 f3;
Form5 f5;
Form6 f6;
int PortNumber;
public string localIp;
string machinnos;
Boolean ready = false ; //线程运行标志
Socket ListenerSock; //Socket
Thread ListenerThre; //端口侦听线程
public IPEndPoint RemoteIPoint; //这里指向发送数据包的目的Ip及端口,EndPoint是IPEndPoint的基类,IPEndPoint可以强转为EndPoint。EndPoint ep = (EndPoint)iep,主要目的是IPEndPoint可以自己写入IP地址和端口
string BeepCode;
string VoiceCode;
public string sendcode; //批量下传注册号的指针、缓冲、重发标志
public bool SendCount;
public int SendAgain;
public int SendPoin;
public int SendPoinMax;
public string[] SendBufStr=new string[7950];
delegate void Update1(string text1,string text2); //线程内更新UI委拖
[DllImport("Iphlpapi.dll")]
private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ready = false;
GetIp();
StartListener();
}
private void GetIp()
{
ArrayList AllIp = new ArrayList();
string name = Dns.GetHostName();
IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
foreach (IPAddress ipa in ipadrlist)
{
if (ipa.AddressFamily == AddressFamily.InterNetwork)
localIp = ipa.ToString();
if (checkip(localIp))
{
AllIp.Add(localIp);
ComboBox1.Items.Add(localIp);
}
}
if (ComboBox1.Items.Count > 0)
{
ComboBox1.SelectedIndex = 0;
localIp = ComboBox1.Text;
}
else {
MessageBox.Show("未能查找到本台电脑安装的网卡,暂不能启动本软件。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Environment.Exit(0); //这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。
}
}
private void StartListener()
{
IPEndPoint LocalPoint;
PortNumber = Convert.ToInt32(TextBox6.Text) ;
while (!ready)
{
try
{
LocalPoint = new IPEndPoint(IPAddress.Parse(localIp), PortNumber);
ListenerSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
ListenerSock.Bind(LocalPoint);
ListenerThre = new Thread(new ThreadStart(ThrListener));
ListenerThre.Start();
ready = true;
}
catch
{
ListenerSock.Close();
ready = false;
MessageBox.Show("有其它应用程序占用了 " + PortNumber.ToString() + " ,请检查并关闭此应用后再打开本程序", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Environment.Exit(0); //这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。
}
}
}
public void ThrListener()
{
while (ready)
{
try
{
EndPoint RemotePoint = new IPEndPoint(System.Net.IPAddress.Any, 0);
byte[] bytes = new byte[1024];
int NumGet = ListenerSock.ReceiveFrom(bytes, ref RemotePoint);
string Msg = Encoding.GetEncoding(936).GetString(bytes, 0, NumGet);
//string Msg = Encoding.UTF8.GetString(bytes, 0, NumGet); //读wifi参数时,要用utf8编码
string dispstr = DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + (" FromIP:" + Convert.ToString(RemotePoint) + " ").Substring(0, 30) + "Data:";
RemoteIPoint =(IPEndPoint)RemotePoint; //获取数据包来源IP及端口,原路回应
this.BeginInvoke(new Update1(EditUi), dispstr, Msg); //显示接收到的数据包,并根据情况回应设备
}
catch(Exception ex )
{
this.BeginInvoke(new Update1(EditUi), DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")+" ",ex.Message );
}
}
}
private void EditUi(string text1, string Msg) //解析显示接收到的数据包,并对设备进行回应
{
if (ListBox1.Items.Count > 50) { ListBox1.Items.Clear();}
ListBox1.Items.Add(text1 + Msg);
ListBox1.SelectedIndex = ListBox1.Items.Count - 1;
string DevRecFramesStr;
string DevBufferIpAddrStr;
string DevBufferMachinStr;
string DevBufferCardidStr;
string DevBufferDatetimeStr;
string DevBufferUseMoneryStr;
string DevBufferUseTimeStr;
string DevBufferMaskStr;
string DevBufferGatewayStr;
string DevBufferRemoteAddrStr;
string DevBufferPort;
string DevBufferNumberDecStr;
string DevBufferGatewayStrMAC;
string DevBufferRemoteAddrMACStr;
string DevBufferMACSearchStr;
string DevBufferSerialNumStr;
string DevBufferStaryStr;
string DevBufferRecordAddStr;
string DevBufferAllNoStr;
string DevBufferInputKeyStr;
string DevBufferCommandStr;
string DevBufferFunctionStr1;
string DevBufferFunctionStr2;
string DevBufferQrcodeInfStr;
string DevBufferReaderStr;
string DevBufferDoorNoStr;
string DevBufferDelayStr;
string DevBufferPasswPropStr;
string DevBufferPassWStr;
string DevBufferStateStr;
string DevBufferRandomCode;
string DevBufferScanStr;
string MACSTC;
string MACCH;
string iswifi;
string wifidhcp;
string Sendinf;
int poi;
ListViewItem plist;
string[] dataArray = Msg.Split(new char[2] { ',', ',' });
switch (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)
{ //2018年以后的设备有唯一硬件序号*/
DevBufferSerialNumStr = dataArray[6];
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
string SystemTimeStr = DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
if( DevBufferDatetimeStr.Substring(0, 16) != SystemTimeStr.Substring(0, 16) ) //判断设备时间是否正确,不正确就更正时间
{
Response("003," + DevBufferMachinStr+","+SystemTimeStr);//更新设备时钟
}
TextBox3.Text = DevBufferDatetimeStr;
break;
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){
DevBufferSerialNumStr = dataArray[12]; //2018年以后的设备有唯一硬件序号
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
//此处加入业务对数据库的查、增、删、减操作
//用050指令返回开门成功,051指令返回开门失败,正式系统开发时要有重发机制
switch( VoiceCode)
{
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "10":
case "11":
case "12":
case "13":
case "14":
case "15": //提示警告不开门
Sendinf = "051," + DevBufferMachinStr + "," + DevBufferCardidStr + "," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode;
break;
default : //显示并开门
Sendinf = "050," + DevBufferMachinStr + "," + DevBufferCardidStr + "," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode + "," + DevBufferReaderStr + "," + DevBufferDoorNoStr + "," + NumericUpDown1.Value.ToString() + "," + NumericUpDown2.Value.ToString();
break;
}
Response(Sendinf);
break;
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 (dataArray.Length > 9)
{
DevBufferSerialNumStr = dataArray[9]; //2018年以后的设备有唯一硬件序号
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
//此处加入业务对数据库的查、增、删、减操作
//用050指令返回开门成功,051指令返回开门失败,正式系统开发时要有重发机制
switch (VoiceCode)
{
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "10":
case "11":
case "12":
case "13":
case "14":
case "15": //提示警告不开门
Sendinf = "051," + DevBufferMachinStr + "," + DevBufferInputKeyStr + "," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode;
break;
default: //显示并开门
Sendinf = "050," + DevBufferMachinStr + "," + DevBufferInputKeyStr + "," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode + "," + DevBufferReaderStr + "," + NumericUpDown1.Value.ToString() + "," + NumericUpDown2.Value.ToString();
break;
}
Response(Sendinf);
break;
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 (dataArray.Length > 9)
{
DevBufferSerialNumStr = dataArray[9]; //2018年以后的设备有唯一硬件序号
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
break;
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 (dataArray.Length > 9)
{
DevBufferSerialNumStr = dataArray[9]; //2018年以后的设备有唯一硬件序号
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
f6.TextBox3.Text = "继电器号:" + DevBufferInputKeyStr + ",继电器状态:" + DevBufferReaderStr + ",门磁未关秒数:" + DevBufferDelayStr + ",门磁报警状态:" + DevBufferStateStr;
break;
case "154": //接收到实时考勤门禁机卡离开感应区
DevRecFramesStr = dataArray[1]; //包序列号
DevBufferIpAddrStr = dataArray[2]; //终端IP
DevBufferRemoteAddrStr = dataArray[3]; //远程电脑指机IP
DevBufferMachinStr = dataArray[4]; //机号
DevBufferCardidStr = dataArray[5]; //十位物理卡号
DevBufferSerialNumStr = dataArray[6]; //设备有唯一硬件序号
break;
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]; //总计录数*/
DevBufferSerialNumStr = "";
if (dataArray.Length > 12)
{
DevBufferSerialNumStr = dataArray[13]; //2018年以后的设备有唯一硬件序号
}
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
if (!checkDateTime(DevBufferUseTimeStr)) { DevBufferUseTimeStr = "9999-99-99 99:99:99"; } //如果接收到非法的消费时间,将消费时间改为"9999-99-99 99:99:99"才能清除。
//此处加入这里对脱网记录进行处理,对数据库的查、增、删、减操作
if (CheckBox3.Checked) //清除设备内当前这条已上传的记录,驱动设备继续上传剩下的记录
{
Sendinf = "055," + DevBufferMachinStr + "," + DevBufferCardidStr + "," + DevBufferUseTimeStr + "," + DevBufferRecordAddStr;
Response(Sendinf);
}
break;
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位十六进制)
switch (DevBufferStaryStr)
{
case "0":
f6.TextBox3.Text = "IP:" + DevBufferIpAddrStr + " 开门成功";
f6.TextBox2.Text = DevBufferRandomCode;
break;
case "1":
f6.TextBox3.Text = "IP:" + DevBufferIpAddrStr + " 开门密码认证失败!";
f6.TextBox2.Text = DevBufferRandomCode;
break;
case "2":
f6.TextBox3.Text = "IP:" + DevBufferIpAddrStr + " 开门密码认证失败超过6次,需等待一段时间后再能再次接收058指令(防暴力破解)";
f6.TextBox2.Text = DevBufferRandomCode;
break;
case "3":
f6.TextBox3.Text = "IP:" + DevBufferIpAddrStr + " 不允许此时间段开门";
f6.TextBox2.Text = DevBufferRandomCode;
break;
}
break;
case "159": //接收到实时考勤门禁机心跳信息
DevRecFramesStr = dataArray[1]; //包序列号
DevBufferIpAddrStr = dataArray[2]; //终端IP
DevBufferRemoteAddrStr = dataArray[3]; //远程电脑指机IP
DevBufferMachinStr = dataArray[4]; //机号
DevBufferQrcodeInfStr = dataArray[5]; //信息类型
DevBufferFunctionStr1 = dataArray[6]; //继电器状态(bit0为第1门bit1为第2门)
DevBufferFunctionStr2 = dataArray[7]; //消防输入状态
DevBufferRandomCode = dataArray[8]; //&动态随机码(8位十六进制)
DevBufferDatetimeStr = dataArray[9]; //日期时间
DevBufferSerialNumStr = dataArray[10]; //设备硬件号
try
{
f6.TextBox2.Text = DevBufferRandomCode;
}
catch { }
break;
case "170": //接收门禁外接双USB扫描枪模块
DevRecFramesStr = dataArray[1]; //包序列号
DevBufferIpAddrStr = dataArray[2]; //终端IP
DevBufferRemoteAddrStr = dataArray[3]; //远程电脑指机IP
DevBufferMachinStr = dataArray[4]; //机号
DevBufferScanStr = dataArray[5]; //扫码信息
DevBufferReaderStr= dataArray[6]; //对应门的扫描枪号
DevBufferDoorNoStr = dataArray[7]; //门或继电器号*/
DevBufferDelayStr = dataArray[8]; //门磁未关秒数,0表示已关*/
DevBufferUseTimeStr = dataArray[9]; //扫码时间
DevBufferSerialNumStr = dataArray[10]; //设备有唯一硬件序号
Response("001," + DevRecFramesStr); //向设备回应001+包序列号,表示已收到信息,否则设备会连续发三次
switch( VoiceCode)
{
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "10":
case "11":
case "12":
case "13":
case "14":
case "15": //提示警告不开门
Sendinf = "051," + DevBufferMachinStr + "," + DevBufferReaderStr + "," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode;
break;
default : //显示并开门
Sendinf = "050," + DevBufferMachinStr + ",0," + TextBox5.Text.Trim() + "," + NumericUpDown2.Value.ToString() + "," + BeepCode + "," + VoiceCode + "," + DevBufferReaderStr + "," + DevBufferDoorNoStr + "," + NumericUpDown1.Value.ToString() + "," + NumericUpDown2.Value.ToString();
break;
}
Response(Sendinf);
break;
}