asp.net 集成 Tcp Server 服务
工程源码下载:GPS定位系统VUE版本源码下载
Link库的详细实现,请参考项目源码!!
在上一节中,我们已经把当前项目需要的通讯协议格式制定好了,接下来就是教大家如何用程序来实现我们的通讯。
当前章节是要实现后端部分的TCP通讯,这里需要集成一个自定义的库“Link”,该库的架构可以参考《如何实现TCP通信》章节。该章节的基本架构和自定义库“Link”的架构是一样的。当然,你也可以直接去集成《如何实现TCP通信》章节的功能模块。
在本章节中,ASP.Net主要是作为TCP Server模式来运行,这样可以确保我们的服务器能够对接多台下位机设备,Link库的添加方法和DbEntity库的添加方法一样,同样是通过新建工程的方式添加,然后将《如何实现TCP通信》章节的代码拷贝进去。
关于自定义的“Link”库,在工程源码里面都有集成,对于初学者来说,这个库可能会比较复杂,可以先尝试去集成《如何实现TCP通信》章节的功能模块,再回头来看“Link”库,可能就会简单一些了,“Link”库的目录结构说明如下,新建过程我这里就不讲解了,我这里只教大家如何使用这个Link库。
“Link”库的目录结构说明如下:

其中GpsModel.cs文件和GpsModel目录属于成对出现的,这里表示的是GPS类型的下位机设备,这里注意了,这文件是成对出现的,比如GPS的一组、温湿度传感器的一组,以此类推。
我们这里采用的校验算法是和校验,代码如下:
/// <summary>
/// 和校验
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static byte GetSum(this byte[] date)
{
int value = 0;
if (date.Length > 0)
{
for (int i = 0; i < date.Length; i++)
{
value ^= date[i];
}
}
return (byte)(value & 0x00FF);
}
数据包的解析和组装都在Package.cs文件中。
数据包组装方法如下:
/// <summary>
/// 按标准格式组装成数据包,并返回
/// </summary>
/// <param name="equi">当前的设备类型</param>
/// <param name="equiNo">设备号</param>
/// <param name="pro">功能码</param>
/// <param name="cont">数据</param>
public Package(byte equi, byte[] equiNo, byte pro, byte[] cont)
{
// 数据格式:网络识别码 + 设备类型 + 设备号 + 包号 + 功能码 + 内容 + 校验码
// 网络识别码
netID = Res.NetID;
// 当前的设备类型
equipment = equi;
// 设备号
equipmentNo = equiNo;
// 包号
packageNo = Res.GetPackageNo();
// 功能码
program = pro;
// 内容
context = cont;
// 组装成list
List<byte> b = new List<byte>();
b.Add(netID);
b.Add(equipment);
b.AddRange(equipmentNo);
b.AddRange(packageNo);
b.Add(program);
b.AddRange(context);
// 校验
sum = b.ToArray().GetSum();
b.Add(sum);
Data = b.ToArray();
}
数据包解析方法如下:
/// <summary>
/// 按标准格式解析接收到的数据包
/// </summary>
/// <param name=""></param>
public Package(byte[] bytes)
{
try
{
Data = bytes;
int len = bytes.Length;
netID = bytes[0]; // 网络识别码
if (netID != Res.NetID) { errcode = $"网络设备号错误:{netID}"; return; }
equipment = bytes[1]; // 设备类型
equipmentNo = bytes.Skip(2).Take(2).ToArray(); // 设备号
packageNo = bytes.Skip(4).Take(2).ToArray(); // 包号
program = bytes[6]; // 功能码
context = bytes.Skip(7).Take(len - 8).ToArray(); // 数据
sum = bytes.Last();
byte s = (bytes.Take(len - 1).ToArray()).GetSum();
if (s != sum) errcode = "和校验失败";
}
catch
{
errcode = "数据包解析失败!";
}
}
当集成完“Link”库后,需要在我们的工程中引用“Link”,如下:

然后修改ServerInit.cs文件,初始化我们的TCP Server,修改如下:
using DbEntity;
using Serilog;
using WebApplicationApi.Helpers;
using WebApplicationApi.packs;
namespace WebApplicationApi
{
public class ServerInit
{
public ServerInit(string sql, string tcp)
{
// 打印mysql的连接信息
Log.Information(sql);
// 设置mysql 连接
MyDbContext.config = sql;
// 数据库初始化,如果报表不存在,会自动生成
DbInit();
// 通信数据回调事件
EventInit();
// 启动TCP Server,传入配置的IP信息
Res.StartLink(tcp);
// 启动gps队列
GpsHelper.Start();
}
/// <summary>
/// 启动数据库
/// </summary>
private void DbInit()
{
try
{
using (MyDbContext db = new MyDbContext())
{
db.Database.EnsureCreated();
}
}
catch (Exception e)
{
Log.Error(e.Message);
}
}
/// <summary>
/// 事件初始化
/// </summary>
private void EventInit()
{
// 保存GPS数据
Link.Res.SenseDataMsg = (devid, userid, longitude, latitude) =>
{
try
{
GpsHelper.Write(new GpsQuePack(devid, userid, longitude, latitude));
}
catch (Exception e)
{
Log.Information(e.Message);
}
};
// 后面可以扩展
/* ... */
}
}
}
修改完ServerInit之后,我们还需要添加如下3个文件。【详细实现,请参考源码】

想办法在数据库gpsdemo中新建个用户,然后打开模拟器,将ID填入模拟器中。

此时,就可以用模拟器进行连接测试了,测试效果如下,到这一步,我们所有的tcp功能就集成完成了。
