储物柜soket通信协议和中间件实现技术细节
一、中间件程序的职责:
1)对柜机提供soket长连接的服务器端,就是soket server。可提供上万的客户端同时连接。用来实时响应控制请求,中间件必须随时知道某个柜机的在线状态,外部请求时才能判断是否能够转发消息。
中间件监听的端口是5880,socket连接的协议是tcp/ip。目前没有加密,明文传输。
流程说明:
签到:
柜机socket client发起连接请求,中间件socket接受连接之后,
柜机socket client先对中间件socket server发送消息(格式:“ bufferbox_sign_in”+“:”+设备号,如 bufferbox_sign_in:KDL36000001)
中间件程序把柜机KDL36000001显示为在线状态。
长连接中断后重连
柜机socket client和中间件socket server建立连接后是有定时发送心跳包的,
柜机socket client每过30秒检查和中间件socket serverd的连接状态,发起0字节的发包请求,如果发生异常则实际连接情况发生变化,
柜机socket client断开连接,重新尝试建立连接重新发起签到。
2)对外部暴露RESTful风格的api,供外部各种应用和程序调用,响应外部的http get/post请求。
api原型,.net webapi:
[HttpGet] /// <summary> /// 储物柜取物开箱接口(取件) /// </summary> /// <param name="StationNo">设备唯一编号 设备不存在或者设备编号有误!</param> /// <param name="CellNo">箱格编号</param> /// <returns></returns> public ApiActionResult BufferBox_Collect(string StationNo, string CellNo) { var result = new ApiActionResult() { Success = false, Result = null, Message = "操作失败。" }; string msg = string.Empty; using (var db = new BufferBoxDBEntities()) { var stationEntity = db.station_signin_session.Where(st => st.SessionDict == StationNo).FirstOrDefault(); if (stationEntity == null) { result.Message = "设备不存在或者设备编号有误!"; result.Result = ""; return result; } #region API_Request_session var requestEntity = new API_Request_session { API_Request_IP = Request.GetClientIpAddress(), RequestID = Guid.NewGuid(), RequestData = CellNo + "|Collect", RequestDataTime = DateTime.Now, ResultData = JsonConvert.SerializeObject(new CommandResultDTO { CellNo = CellNo, Action = "取件", ResultMessage = "中间件已转发,设备还未回复。" }), ExecuteFlag = false, StationNo = StationNo }; db.API_Request_session.AddObject(requestEntity); #endregion db.SaveChanges(); //Com.DataCool.DotNetExpand.LogHelper.Info(JsonConvert.SerializeObject(requestEntity)); msg = "api_request:" + JsonConvert.SerializeObject(requestEntity); result.Success = true; result.Message = "设备已经受理请求。"; result.Result = requestEntity.RequestID.ToString(); } if (!string.IsNullOrEmpty(msg)) { Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(IPAddress.Parse(conf.AppSettings.Settings["Middleware_IP"].Value), Convert.ToInt32(conf.AppSettings.Settings["Middleware_PORT"].Value))); clientSocket.Send(Encoding.UTF8.GetBytes(msg)); } catch { } } return result; }
流程说明:
webapi响应外部的http get请求后,根据api的参数StationNo,CellNo获取到本次请求的设备和对应箱格。然后向中间件socket server发起一个socket client连接,建立连接后发送消息“api_request”+“:”+请求内容(后面附格式),中间件在内存上下文找到柜机socket client连接对象转发刚才的webapi发出的消息。柜机socket client收到中间件socket server的api_request消息 马上执行对控制板发送开锁指令。然后立即回复中间件socket server消息格式是“command_result”+“:”+处理过的请求内容(后面附格式) 中间件socket server收到消息将本次请求的结果修改为执行成功,这样完成了一次完整的操作
附请求内容json格式:
api_request:{"$id":"1","RequestID":"066a395a-486f-4e93-b782-fbf889e1d52f","Token":null,"RequestData":"11|Deposit","ResultData":"{\"CellNo\":\"\",\"ResultMessage\":\"中间件已转发,设备还未回复。\",\"Action\":\"存件\"}","RequestDataTime":"2016-07-16T12:00:53.9329622+08:00","ResultDataTime":null,"ExecuteFlag":false,"API_Request_IP":"183.70.83.165","StationNo":"SHYH24000001","EntityKey":{"$id":"2","EntitySetName":"API_Request_session","EntityContainerName":"BufferBoxDBEntities","EntityKeyValues":[{"Key":"RequestID","Type":"System.Guid","Value":"066a395a-486f-4e93-b782-fbf889e1d52f"}]}}
RequestID是每次外部请求的guid,代表每次请求的唯一请求编号,
RequestData是请求的实际内容
ResultData是另一个api要回复外部请求的内容
RequestDataTime是发起请求的时间
ResultDataTime是柜机客户端回应的时间
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool2016_bufferbox_middleware.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构