Csharp实例:武汉智能安检闸机数据接收和解析
项目介绍: 本实例主要是接收安检闸机的数据解析并显示到界面上,只做功能实现,不做界面美化 硬件:闸机一个、网线一根、电脑主机 开发环境:vs2017 系统:win10 涵盖知识点:tcp通讯、文件写入、多线程,委托、类型转换等
软件操作流程:
点击开始监听按钮,8999要是未被占用则开启监听,然后人刷身份证通过安检闸机就可以接收到数据
数据格式截图:
安检闸机图片:
知识点介绍:
1. socket.Listen(10); 官方给出的解释:挂起连接队列的最大长度。
连接队列,即连接池,也就是要保证挂起的连接池中至少要有10个连接 我解释一下,为什么要提前准备10个挂起的连接,原因就是每当一个新用户接入进来时,就需要立即创建一个socket,创建也需要时间和消耗系统资源,这样就会影响高并发的性能 ,用不用,先放那,用的时候直接取即
2. Socket clientSocket = socket.Accept();
AcceptSocket是同步的,你可以用异步通讯的BeginAcceptSocket或者用多线程。没有请求到达,就会“卡”住,术语叫程序阻塞,socket同步通讯就是这个步骤,执行到AcceptSocket就会阻塞等待请求,直到有请求到达时,才执行后面的语句,并且处理这个请求
3. while (true) 因为组要一直监听,所以得死循环;
4. 开启一个后来线程,不然主界面会假死 new Thread(delegate () {主体代码;}) { IsBackground = true }.Start();
5.从其它线程访问主线程控件需要委托,不然界面不会有数据的
this.Invoke((EventHandler)delegate { richTextBox1.Text += “”; });
完整代码如下:
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Text;
using System.Drawing;
namespace TcpRecive
{
public partial class mainForm : Form
{
public mainForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "8999";
}
public void tcpRecive(int port)
{
if (PortIsUse(port))
{
label1.Text = "端口" + port.ToString() + "被占用"; return;
}
else label1.Text = "端口" + port.ToString() + "没有占用,监听已开启";
new Thread(delegate ()
{
int recv;//定义接收数据长度变量
//IPAddress ip = IPAddress.Parse("192.168.1.119");//接收端所在IP 192.168.1.119换成127.0.0.1不可以为什么?
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, port);//接收端所监听的接口,ip也可以用IPAddress.Any
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一个Socket对象
socket.Bind(ipEnd);//绑定套接字到一个IP地址和一个端口上(bind());
//官方给出的解释:挂起连接队列的最大长度。
//连接队列,即连接池,也就是要保证挂起的连接池中至少要有10个连接
//我解释一下,为什么要提前准备10个挂起的连接,原因就是每当一个新用户接入进来时,就需要立即创建一个socket,创建也需要时间和消耗系统资源,这样就会影响高并发的性能
//,用不用,先放那,用的时候直接取即可
socket.Listen(10);
while (true)
{
try
{
byte[] data = new byte[70000];//对data清零
Socket clientSocket = socket.Accept(); //一旦接受连接,创建一个客户端
recv = clientSocket.Receive(data);// 或者clientSocket.Receive(data, data.Length, SocketFlags.None);获取收到的数据的长度
if (recv == 0) //如果收到的数据长度小于0,则退出
break;
//string stringData = Encoding.ASCII.GetString(data);
string stringData = Encoding.UTF8.GetString(data);
dataDecode(data);
fileWrite(DateTime.Now.ToString("yy-MM-dd hh:mm:ss") + "n" + stringData);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
})
{ IsBackground = true }.Start();
}
/// <summary>
/// 字节数组转16进制字符串
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string byteToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
public void dataDecode(byte[] data)
{
int dataL = 0, isPass = 0, nameL = 0, ethnicL = 0, sexL = 0, birthdayL = 0, adressL = 0, cardNoL = 0, startTimeL = 0, endTimeL = 0, cardImageL = 0, captureImageL = 0;
string item = "", name = "", ethnic = "", sex = "", birthday = "", adress = "", cardNo = "", startTime = "", endTime = "";
dataL = BitConverter.ToInt32(data, 0);//数据包大小,低字节在前面,高字节在后面
isPass = BitConverter.ToInt32(data, 4);//人证核验结果
nameL = BitConverter.ToInt32(data, 8);//姓名长度
name = Encoding.UTF8.GetString(data, 12, nameL);//姓名
ethnicL = BitConverter.ToInt32(data, 12 + nameL);//民族长度
ethnic = Encoding.UTF8.GetString(data, 16 + nameL, ethnicL);//民族
sexL = BitConverter.ToInt32(data, 16 + nameL + ethnicL);//性别长度
sex = Encoding.UTF8.GetString(data, 20 + nameL+ ethnicL,sexL);//性别
birthdayL = BitConverter.ToInt32(data, 20 + nameL + ethnicL + sexL);
birthday = Encoding.UTF8.GetString(data, 24 + nameL + ethnicL+sexL,birthdayL);//出生日期
adressL = BitConverter.ToInt32(data, 24 + nameL + ethnicL + sexL + birthdayL);
adress = Encoding.UTF8.GetString(data, 28 + nameL + ethnicL + sexL+birthdayL, adressL);//地址
cardNoL = BitConverter.ToInt32(data, 28 + nameL + ethnicL + sexL + birthdayL + adressL);
cardNo = Encoding.UTF8.GetString(data, 32 + nameL + ethnicL + sexL + birthdayL+adressL, cardNoL);//身份证号码
startTimeL = BitConverter.ToInt32(data, 32 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL);
startTime = Encoding.UTF8.GetString(data, 36 + nameL + ethnicL + sexL + birthdayL + adressL+ cardNoL, startTimeL);//身份证起始时间
endTimeL = BitConverter.ToInt32(data, 36 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL);
endTime = Encoding.UTF8.GetString(data, 40 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL+ startTimeL, endTimeL);//身份证终止时间
if (isPass == 1)
item = "人证核验:成功" + "n姓名:" + name + "n民族:" + ethnic + "n性别:" + sex + "n出生日期:" + birthday +
"n地址:" + adress + "n身份证号码:" + cardNo + "n身份证起始时间:" + startTime + "n身份证终止时间:" + endTime;
else
item = "人证核验:失败" + "n姓名:" + name + "n民族:" + ethnic + "n性别:" + sex + "n出生日期:" + birthday +
"n地址:" + adress + "n身份证号码:" + cardNo + "n身份证起始时间:" + startTime + "n身份证终止时间:" + endTime;
cardImageL = BitConverter.ToInt32(data, 40 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL + endTimeL);
MemoryStream ms1 = new MemoryStream(data, 44 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL + endTimeL, cardImageL);
captureImageL = BitConverter.ToInt32(data, 44 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL + endTimeL + cardImageL);
MemoryStream ms2 = new MemoryStream(data, 48 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL + endTimeL+cardImageL, captureImageL);
//ms.Write(data, 44 + nameL + ethnicL + sexL + birthdayL + adressL + cardNoL + startTimeL + endTimeL, cardImageL);
Image img1 = Image.FromStream(ms1);
Image img2 = Image.FromStream(ms2);
this.Invoke((EventHandler)delegate
{
richTextBox1.Text = item;
pictureBox1.Image = img1; //更新在窗体控件上
pictureBox2.Image = img2;
});
ms1.Flush(); ms2.Flush();
ms1.Close(); ms2.Close();
ms1.Dispose(); ms2.Dispose();
}
public void fileWrite(string str)
{
if (!File.Exists("info.txt"))
File.Create("info.txt").Close();//创建文件并关闭
StreamWriter sw = new StreamWriter("info.txt",true);//向文件追加数据
sw.WriteLine(str);
sw.Close();
}
//通过 IPGlobalProperties来获取本机的网络连接的信息,并通过GetActiveTcpListeners找到已用端口,进而可以知道所需的端口是否已被占用
public static bool PortIsUse(int port)
{
bool isUse = false;
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();//找到已用端口
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)//判断是否存在
{
isUse= true;
break;
}
}
return isUse;
}
private void button1_Click(object sender, EventArgs e)
{
tcpRecive(int.Parse(textBox1.Text));
}
}
}
运行结果:
- 10个实用的但偏执的Java编程技术
- 看似诡异的tablespace online问题(r5笔记第95天)
- python2.7进行爬虫POI代码(划分小网格算法)
- 从 Encoder 到 Decoder 实现 Seq2Seq 模型
- python2.7进行爬虫百度POI代码(划分小网格算法)
- 如何通过TTL调试光猫
- 基于树莓派和Tensowflow的物体识别-brain
- SNA中:中心度及中心势诠释(不完整代码)
- 教程 | 基于计算机视觉使用Python和OpenCV计算道路交通
- 干货 | MVP模式在携程酒店的应用和扩展
- memlock过低导致的数据库性能问题(r6笔记第10天)
- OpenCV和SVM分类器在自动驾驶中的车辆检测
- 自动驾驶的模型预测控制
- 【专业技术】使用html5的十大原因
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Windows 安装 MySQL 常见问题
- LootCode-链表排序-Java
- 好久不用 jQuery, 来复习一下
- Spring学习一、组件注册
- 复习 EL 表达式与 JSTL
- Spring 学习二、Bean生命周期相关注解
- 十分钟学会 HTML
- 聊一下会话跟踪技术
- 朝花夕拾之Matlab基础回顾:向量的点积、叉积、混合积
- 详解响应消息 response
- Kubernetes 1.19.0——deployment(3)
- Selenium-01-测试环境搭建使用
- Selenium-02-常用元素定位
- SpringBoot + Vue 前后端分离项目下载视频文件踩坑记录
- Selenium-03-常用方法