1,首先客戶有一堆自動售貨機的設備,設備鏈接socket服務端後 定時發送設備實時狀態做爲心跳信息,而且服務端須要下發信息予以確認。redis
2,須要知道設備的實時在線狀態windows
3,設備須要實現微信,支付寶掃碼支付需求,當客戶買東西的時候選擇掃碼支付時,設備上報產品價格信息,支付方式,服務器下發微信或者支付寶的當面付二維碼。服務器
4,當客戶掃碼支付後,服務器須要下發支付結果。微信
5,設備上報出貨成功或失敗信息,服務器予以回覆確認網絡
6,設備上報現金收款的收款或者退款信息,服務器保存而且下發回覆確認。session
7,服務器後臺須要可以主動的向設備推送廣告信息,而且可以實現掉線設備的廣告推送socket
1,想要服務穩定可靠,那麼首先考慮的是程序的運行方式,固然是以一個windows服務爲宿主的方式來運行最爲可靠,那麼咱們能夠使用TopShelf來構建這樣一個服務宿主tcp
2,實現設備的在線狀態實時可知,咱們須要定時的去判斷這個設備是否在定時給服務器發送心跳信息,這個項目中咱們以超時未發送心跳信息爲標準來衡量他是否在線。微信支付
3,設備數據上報涉及到粘包的處理,設備上報的數據是怎麼樣一個協議,如何來解決粘包的問題,這裏咱們藉助Newlife網絡庫的管道模式來處理粘包spa
4,微信支付寶的掃碼支付如何及時知道客戶付款狀態,而且及時的下發給設備。
1,首先使用的網絡庫是Newlife 新生命團隊的網絡庫
2,構建windows服務使用的是TopShelf
3,狀態的信息保存使用Redis,這裏咱們使用CSRedisCore 這個類庫
4,微信支付寶本次使用的是PaySharp這個庫,二維碼生成使用QrCoder庫
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的初始化,粘包處理,數據接收的一個基本服務端,下面咱們再講如何解決粘包的問題。