使用NewLife网络库构建可靠的自动售货机Socket服务端(一)

最近有个基于tcp socket 协议和设备交互需求,想到了新生命团队的各种组件,所以决定用NewLife网络库作为服务端来完成一系列的信息交互.

第一,首先说一下我们需要实现的功能需求吧

1,首先客户有一堆自动售货机的设备,设备连接socket服务端后 定时发送设备实时状态作为心跳信息,并且服务端需要下发信息予以确认。

2,需要知道设备的实时在线状态

3,设备需要实现微信,支付宝扫码支付需求,当客户买东西的时候选择扫码支付时,设备上报产品价格信息,支付方式,服务器下发微信或者支付宝的当面付二维码。

4,当客户扫码支付后,服务器需要下发支付结果。

5,设备上报出货成功或失败信息,服务器予以回复确认

6,设备上报现金收款的收款或者退款信息,服务器保存并且下发回复确认。

7,服务器后台需要能够主动的向设备推送广告信息,并且能够实现掉线设备的广告推送

第二,我们来分析这个可靠的服务器的大致结构是如何的(仅包含设备实时状态和支付交互)

1,想要服务稳定可靠,那么首先考虑的是程序的运行方式,当然是以一个windows服务为宿主的方式来运行最为可靠,那么我们可以使用TopShelf来构建这样一个服务宿主

2,实现设备的在线状态实时可知,我们需要定时的去判断这个设备是否在定时给服务器发送心跳信息,这个项目中我们以超时未发送心跳信息为标准来衡量他是否在线。

3,设备数据上报涉及到粘包的处理,设备上报的数据是怎么样一个协议,如何来解决粘包的问题,这里我们借助Newlife网络库的管道模式来处理粘包

4,微信支付宝的扫码支付如何及时知道客户付款状态,并且及时的下发给设备。

第三,我们需要用到的第三方类库有哪些

1,首先使用的网络库是Newlife 新生命团队的网络库

2,构建windows服务使用的是TopShelf

3,状态的信息保存使用Redis,这里我们使用CSRedisCore 这个类库

4,微信支付宝本次使用的是PaySharp这个库,二维码生成使用QrCoder库

第四,开始构建的基本的Socket服务吧

1,首先创建一个windows服务,引入Topshelf后

        static void Main(string[] args)
        {
            var rc = HostFactory.Run(x =>                                   //1
            {
                x.Service<DianSocketMain>(s =>                                   //2
                {
                    s.ConstructUsing(name =>new DianSocketMain());                //3
                    s.WhenStarted(tc => tc.Start());                         //4
                    s.WhenStopped(tc => tc.Stop());                          //5
                });
                x.RunAsLocalSystem();                                       //6

                x.SetDescription("售货机socket服务端");                   //7
                x.SetDisplayName("Vending machine socket");                                  //8
                x.SetServiceName("Vendingmachinesocket");                                  //9
                x.OnException(s =>
                {
                    LogerHelper.WriteErroLog("test",s.Message);
                });
            });                                                             //10
        }
DianSocketMain类就是具体的Socket服务端,来看下是如何启动一个基本的socket服务端
public class DianSocketMain
    {
        /// <summary>
        ///网络库服务端 20181225
        /// </summary>
        private NetServer _newLifeServer;
        /// <summary>
        ///
        /// </summary>
        public void Start()
        {
            try
            {
                try
                {   //redis初始化
                    string redisHost = CoomHelper.GetAppSettings("RedisHost", "127.0.0.1:6379");
                    string redisPwd = CoomHelper.GetAppSettings("RedisPwd", "");
                    string prefix = "{device_server}:";
                    string redisConn = $"{redisHost},password={redisPwd},defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix={prefix}";

                    var csredis = new CSRedis.CSRedisClient(redisConn);

                    RedisHelper.Initialization(csredis);
                }
                catch (Exception e)
                {
                    XTrace.WriteLine(e.Message);
                }

                //启动客户端
                StartNewLifeListenClient();
            }
            catch (Exception e)
            {
                XTrace.WriteException(e);
            }

        }
        /// <summary>
        /// 停止win服务
        /// </summary>
        public void Stop()
        {
            try
            {
                if (_newLifeServer != null)
                {
                    _newLifeServer.Dispose();
                }
            }
            catch (Exception e)
            {
                XTrace.WriteException(e);
            }
        }

        /// <summary>
        /// 监听客户端
        /// </summary>
        private void StartNewLifeListenClient()
        {
            try
            {
                XTrace.WriteLine("当前tcp端口号为:" + 9046);
                //创建监听地址和端口
                IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
                var svr = new NetServer(ipAddress, 9046, NetType.Tcp)
                {
                    Log = XTrace.Log,
                    SessionTimeout = 60
                };
                svr.Add<ReciveFilter>();//粘包处理管道
                svr.Received += new EventHandler<ReceivedEventArgs>(NewlifeRecive);//数据接收
                //svr.Error += new EventHandler<ExceptionEventArgs>(NewlifeError);//错误处理
                //svr.OnDisposed+=new EventHandler();
                svr.Start();
                _newLifeServer = svr;
                //XTrace.WriteLine("会话超时时间为:"+svr.SessionTimeout);
            }
            catch (Exception ex)
            {
                XTrace.WriteLine(ex.Message);
            }

        }

        /// <summary>
        /// 数据接收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NewlifeRecive(object sender, ReceivedEventArgs e)
        {
            INetSession session = (INetSession)sender;
            var pk = e.Message as Packet;
            if (pk.Count == 0)
            {
                XTrace.WriteLine("数据包解析错误");
                return;

            }
         }
    }

这里包含的一个有redis的初始化,粘包处理,数据接收的一个基本服务端,下面我们再讲如何解决粘包的问题。

原文地址:https://www.cnblogs.com/yushuo/p/10283622.html

时间: 2024-10-10 01:56:39

使用NewLife网络库构建可靠的自动售货机Socket服务端(一)的相关文章

使用Newlife网络库管道模式解决数据粘包(二)

上一篇我们讲了 如何创建一个基本的Newlife网络服务端 这边我们来讲一下如何解决粘包的问题 在上一篇总我们注册了Newlife的管道处理器 ,我们来看看他是如何实现粘包处理的 svr.Add<ReciveFilter>();//粘包处理管道 首先看一下我们设备的上传数据协议 设备上报的数据包头包含了固定的包头包尾,整个包的数据长度,设备编号. 包头:板卡类型,帧类型 2个字节 0x01 0x70 帧长度: 为两个字节 并且数据的字节序为  高字节在前 ,C#正常默认为低字节在前. 设备号:

基于迅为4418开发板|触控一体机在自动售货机的应用

近几年,随着移动支付在我国发展的越来越迅速,越来越多的无人商店,无人售卖机越来越多,对移动终端的要求也越来越高,如何降低这些设备的开发门槛,让越来越多的人在日常生活中可以更多的接触到这类产品,因此对终端的性能和降低开发门槛提出了更高的要求. 1.自动售货机(Vending Machine,VEM)是能根据投入的钱币自动付货的机器.自动售货机是商业自动化的常用设备,它不受时间.地点的限制,能节省人力.方便交易.是一种全新的商业零售形式,又被称为24小时营业的微型超市. 2.自动售货系统概念及系统原

Java网络编程【Socket服务端和客户端】

Socket 编程大家都不陌生,Java 学习中必学的部分,也是 Java网络编程核心内容之一.Java 网络编程又包括 TCP.UDP,URL 等模块.TCP 对应 Socket模块,UDP 对应 DatagramPacket 模块.URL 对应 URL 模块.其中 TCP 和 UDP 是网络传输协议,TCP 是数据流传输协议,UDP 是数据包传输协议.两者之间的异同就不在这里说了,推荐一本入门书籍 <TCPIP入门经典>.我们开始 Socket 服务端和客户端编程吧. 一.Socket 服

设计模式 状态模式 以自动售货机为例

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/26350617 状态模式给了我眼前一亮的感觉啊,值得学习~ 先看定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类.定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的. 下面使用个例子来说明状态模式的用法,现在有个自动售货机的代码需要我们来写,状态图如下: 分析一个这个状态图: a.包含4个状态(

查询自动售货机中的商品价格

问题描述:假设自动售货机出售四种商品,在屏幕上显示以下菜单(编号和选项),用户可以连续查询商品的价格,当查询次数超过5次时,自动退出查询:不到5次时,用户可以选择退出.当用户输入编号1~4,显示相应的商品价格(保留1位小数):输入0,退出查询:输入其他编号,显示价格为0. int choice,i; double price; for(i=1;i<=5;i++){ //以下5行显示菜单 printf("[1]Select crisps\n"); //查询薯片价格 printf(&

ios开发之自动售货机的设计与实现

// // main.m // 自动售货机 // /* 自动售货机系统是一个无人售货系统.售货时,顾客把钱投入机器的投币口中, 1.机器检查纸币或者硬币的特点,有效的硬币是一元,五角,有效纸币是十元,五元,其它货币都认为是假币,将其从退币口退出. 2.当机器接到有效的硬币后,把货币放入到储藏箱中,顾客支付的货币根据货币的面值进行累加. 3.自动货机装有物品分配器,每个物品分配器,包含了零个或多个价格相同的物品,顾客通过选择物品分配器来选择商品,如果物品分配其中有商品,而顾客支付的货币部大于该商品

自动售货机是怎么赚钱的

自动售货是算是一种全新的新零售业态,它有投资小,回报快,管理模式简单等特点.从自动售货机进入中国市场发展以来,它的便捷性有效的提升了人们生活的质量.但是,从初期的各方压力与技术需求没有达到市场所需,所以国内的自动售货机一直不温不火. 随着时间推移.国内经济的发展,人工成本,店铺租金的增长,许多地区的商业配套设施无法再满足人们的需求时,更多的人开始追求即时随性,便捷性的消费方式.再加上互联网的覆盖,移动式支付技术提升之下,迅速的引领中国的零售市场.24小时营业服务,低成本,智能化等优势打开了无人零

7-6 自动售货机 (30分)

如图所示的简易自动售货机,物品架1.2上共有10样商品,按顺序进行编号分别为1-10,标有价格与名称,一个编号对应一个可操作按钮,供选择商品使用.如果物架上的商品被用户买走,储物柜中会自动取出商品送到物架上,保证物品架上一定会有商品.用户可以一次投入较多钱币,并可以选择多样商品,售货机可以一次性将商品输出并找零钱. 用户购买商品的操作方法是: (1)从“钱币入口”放入钱币,依次放入多个硬币或纸币.钱币可支持1元(纸币.硬币).2元(纸币).5元(纸币).10元(纸币),放入钱币时,控制器会先对钱

C#骏鹏自动售货机接口

MachineJP类: 第1部分:串口初始化,串口数据读写 using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using MachineJPDll.Models; us