江苏省建设厅网站,做网站需要哪些步骤,商业性质网站设计,网站怎么做rss在上一篇文章《基于mina框架的GPS设备与服务器之间的交互》中#xff0c;提到之前一直使用superwebsocket框架做为IIS和APP通信的媒介#xff0c;经常出现无法通信的问题#xff0c;必须一天几次的手动回收程序池#xff0c;甚至重起服务器#xff0c;通常周末接到一个陌生… 在上一篇文章《基于mina框架的GPS设备与服务器之间的交互》中提到之前一直使用superwebsocket框架做为IIS和APP通信的媒介经常出现无法通信的问题必须一天几次的手动回收程序池甚至重起服务器通常周末接到一个陌生电话就是说客户端无法登录了说多了都是泪。痛定思痛开始找解决方案其实superwebsocket以IIS做为宿主就注定他可能不稳定了当然它部署非常方便为了稳定我开始尝试使用SuperSocket当然这也注定了后期部署会麻烦些生活就是这样哈鱼和熊掌难兼得。学习一个新东西就如同一个打怪升级做任务的历程其中有数不清的陷阱当然也有绚丽景色。关于服务WCF等几乎都是第一次运用其中肯定有很多不对的地方还请了解的朋友们指出来以免误了别人。对于SuperSocket之前也只是听说过本次也只是简单的应用如有应用不对或者说得不对的地方还请江大渔同学指出。另外江大牛做的事让我的开发变得简单了在此对其表示由衷的感谢和敬佩 消息传递流程 消息传递流程如图1所示创建一个Windows Service并启动superSocket发布一个WCF以Windows Service做为宿主随服务启动与关闭。 IIS通过WCF传递消息给Windows Service然后再传给superSocket再传递给android客户端客户端上传坐标处理给superSocket再保存于数据库。 图1 SuperSocket 以下内容是摘自其官网大家可以自行查看SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架。你无须了解如何使用 Socket, 如何维护 Socket 连接和 Socket 如何工作但是你却可以使用 SuperSocket 很容易的开发出一款 Socket 服务器端软件例如游戏服务器GPS 服务器, 工业控制服务和数据采集服务器等等。-- http://www.supersocket.net/ 实现自己的AppSessionAppServer 下载最新版源码目前最新版应该是1.6.3好像是马上要发布1.6.4了吧。解决方案如图2目前我只是简单的应用源码就没细看了其实也看不懂哈哈。 图2 其文档中如下描述 AppSession 代表一个和客户端的逻辑连接基于连接的操作应该定于在该类之中。你可以用该类的实例发送数据到客户端接收客户端发送的数据或者关闭连接。 AppServer 代表了监听客户端连接承载TCP连接的服务器实例。理想情况下我们可以通过AppServer实例获取任何你想要的客户端连接服务器级别的操作和逻辑应该定义在此类之中。 所以通常情况要根据自己的业务来实现自己的AppSessionAppServer。如我需求在session断开时修改app状态或者我的AppSession有自己特殊的属性。下面是我实现的自己的AppSessionNoticeSessionAppServerNoticeServer有兴趣可以瞥下。 NoticeSession代码如下 using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using System.Threading;
using Hangjing.SQLServerDAL.serverinterface;namespace SuperSocket.SocketService
{public class MESSAGETYPE{/// summary/// 1表示消息/// /summarypublic const uint MSG 1;/// summary/// 0表示订单/// /summarypublic const uint ORDER 0;}/// summary/// 自定义连接类MySession继承AppSession并传入到AppSession /// /summarypublic class NoticeSession : AppSessionNoticeSession{bool isSendMessage false;public StringDictionary Cookies { get; private set; }/// summary/// 数据编号配送员或者商家编号等/// /summarypublic int DataID{get;set;}/// summary/// 类型1表示骑士2表示商家/// /summarypublic int Type{set;get;}/// summary/// 用户名;/// /summarypublic String UserName{get;set;}/// summary/// 密码/// /summarypublic String Password{get;set;}protected override void OnSessionStarted(){}protected override void HandleUnknownRequest(StringRequestInfo requestInfo){//Logger.Debug(NoticeSession.OnSessionStarted:Unknow request);}protected override void HandleException(Exception e){//Logger.Debug(NoticeSession.OnSessionStarted:Unknow request);}protected override void OnSessionClosed(CloseReason reason){Logout();base.OnSessionClosed(reason);}/// summary/// 根据登录的参数保存cookie ,并设置属性/// /summarypublic void SetCookie(string cookieValue){var cookies new StringDictionary();if (!string.IsNullOrEmpty(cookieValue)){string[] pairs cookieValue.Split(;);int pos;string key, value;foreach (var p in pairs){pos p.IndexOf();if (pos 0){key p.Substring(0, pos).Trim();pos 1;if (pos p.Length)value p.Substring(pos).Trim();elsevalue string.Empty;cookies[key] Uri.UnescapeDataString(value);}}}this.Cookies cookies;this.UserName Cookies[name];this.Password Cookies[password];this.Type Convert.ToInt32(Cookies[type]);}/// summary/// 向客户端发送消息0 表示订单 1表示消息/// /summary/// param nametype0 表示订单 1表示消息/param/// param namemessage消息内容json/parampublic void SendMessage(uint type, String message){while (isSendMessage){Thread.Sleep(1);}isSendMessage true;String value ;switch (type){case MESSAGETYPE.ORDER:value ORDER:: message;break;case MESSAGETYPE.MSG:value MSG:: message;break;}this.Send(value);isSendMessage false;}/// summary/// session退出对应骑士下线/// /summarypublic void Logout(){if (DataID ! 0 Type 1){APPUser user new APPUser(this.UserName, this.Password, this.SessionID, this.Type);if (user.app ! null){user.app.UpdateLoginState(this.SessionID, 0);}}}/// summary/// 根据编号为类型获取session/// /summary/// param nameid/param/// param nametype/param/// returns/returnspublic NoticeSession GetSession(int id, int type){NoticeSession session this.AppServer.GetAllSessions().Where(a a.DataID id a.Type type).FirstOrDefault();if (session ! null){return session;}else{return null;}}}
} View Code NoticeServer代码如下 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Text;5 using SuperSocket.SocketBase;6 using SuperSocket.SocketBase.Config;7 using SuperSocket.SocketBase.Protocol;8 using Hangjing.SQLServerDAL.serverinterface;9
10 namespace SuperSocket.SocketService
11 {
12 /// summary
13 /// 自定义服务器类MyServer继承AppServer并传入自定义连接类MySession
14 /// /summary
15 public class NoticeServer : AppServerNoticeSession
16 {
17 protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
18 {
19 return base.Setup(rootConfig, config);
20 }
21
22 protected override void OnStarted()
23 {
24 base.OnStarted();
25 }
26
27 protected override void OnStopped()
28 {
29 base.OnStopped();
30 }
31
32 /// summary
33 /// 输出新连接信息
34 /// /summary
35 /// param namesession/param
36 protected override void OnNewSessionConnected(NoticeSession session)
37 {
38 base.OnNewSessionConnected(session);
39 //输出客户端IP地址
40 //session.Logger.Debug(\r\n NoticeServer.OnNewSessionConnected- session.LocalEndPoint.Address.ToString() :连接);
41
42 }
43
44 /// summary
45 /// 输出断开连接信息
46 /// /summary
47 /// param namesession/param
48 /// param namereason/param
49 protected override void OnSessionClosed(NoticeSession session, CloseReason reason)
50 {
51 //输出客户端IP地址/span
52 //session.Logger.Debug(\r\n NoticeServer.OnSessionClosed- session.LocalEndPoint.Address.ToString() :断开 dataid session.DataID Type session.Type);
53 //退出
54 if (session.DataID ! 0)
55 {
56 APPUser user new APPUser(session.UserName, session.Password, session.SessionID, session.Type);
57 if (user.app ! null)
58 {
59 user.app.UpdateLoginState(session.SessionID, 0);
60 }
61 }
62 base.OnSessionClosed(session, reason);
63 }
64
65 }
66 } View Code 实现自己的消息处理机制 消息都会进到MainService.NewRequestReceived 方法中所以我在这里处理自己的消息。默认消息机制里会把消息序列化为 StringRequestInfo这个对像包含Key和Body默认是用空格分隔的。我主要实现app登录建立链接和app上传坐标等两个消息NewRequestReceived 方法代码如下 /// summary/// 收到新的消息/// /summary/// param namesession/param/// param namerequestInfo/paramvoid NewRequestReceived(NoticeSession session, StringRequestInfo requestInfo){//session.Logger.Debug(Key requestInfo.Key |body requestInfo.Body);switch (requestInfo.Key){case Cookie:://这里为了兼容原来的app登录发送的数据{session.SetCookie(requestInfo.Body);User user new User(session);Thread thdProcess new Thread(user.LoginThread);thdProcess.Start();}break;case GPS:{string json requestInfo.Body;if (session.DataID 0 json ){return;}User user new User(session,json);Thread thdProcess new Thread(user.UploadGPS);thdProcess.Start();}break;}} View Code LoginThread 主要实现验证用户名密码后返回用户相关信息具体代码如下 /// summary/// 登录函数/// /summarypublic void LoginThread(){String state ;String message ;APPUser user new APPUser(session.UserName, session.Password, session.SessionID, session.Type);if (user.app null){session.Logger.Debug(登录 session.UserName type session.Type 对像为空);return;}int userid user.app.APPLogin(session.UserName, session.Password, session.SessionID);if (userid 0){NoticeSession ol session.GetSession(userid, session.Type);if (ol ! null){state -2;message Login::{\userid\:\ session.DataID.ToString() \,\state\:\ state \};ol.Send(message);Thread.Sleep(2);ol.Close();}session.DataID userid;state 1;message user.app.getLoginJSON(userid,state);message Utils.ToUTF8(message);session.Send(message);return;}else{state -1;message Login::{\userid\:\ session.DataID.ToString() \,\state\:\ state \};}session.Send(message);Thread.Sleep(2);session.Close();} View Code 考虑到可能会有骑士商家取餐员等对像同时存在为了保证服务程序的通用性抽象出每个对像的相同操作。面向接口进行编程如下图 经过以上简单步骤运行InstallService.bat即可创建服务监听指定端口了。可用TCPUDP测试工具简单测试下看效果如下图 android客户端方面是我同事基于mina实现的这里我就不介绍了其实我也不太懂我只是简单的把他原来以websocket协议实现的修改成了纯数据的了。 创建WCF服务库 当时在考虑如果把消息如把订单调度给某个配送员了传给Windows Service时考虑了多个方法想过用数据库想过用消息队列但是都觉得不太好当WCF飘过脑海时一下子觉得这个可行其实在此之前我也只是听过说而已也许就是因为不熟悉觉得神奇才让我觉得稀奇吧。说干就干看了几篇文章实现了一个简单的WCF。UserNoticeService.cs实现代码如下只有一个简单的方法 using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;namespace Hangjing.WCFService
{[ServiceBehavior(InstanceContextMode InstanceContextMode.Single)]public class UserNoticeService : IUserNoticeService{/// summary/// 添加消息/// /summary/// param nameuserid用户编号/param/// param nameusertype用户类型 1表示骑士2表示商家/param/// param namemessagetype消息类型 消息类型0表示订单1表示纯消息。/param/// param namemessage消息json/parampublic void AddMessage(int userid, int usertype, int messagetype, string message){NoticeInfo model new NoticeInfo();model.UserId userid;model.UserType usertype;model.MessageType messagetype;model.Message message;NoticeManager nm NoticeManager.GetInstance();nm.Add(model);}}
} View Code 使用委托及时传递消息 当UserNoticeService.AddMessage 接收到消息后如何传递给 Windows Service时也纠结了好久直到就快放弃思考准备用消息队列来实现时才想到委托。这个东西吧一直觉得很多神奇之前也花了很多时间去理解一直觉得似懂非懂的感觉原来是没有真正的应用。代码部分就比较简单了以下是NoticeManager.cs相关代码在UserNoticeService.AddMessage中执行添加的方法。 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;namespace Hangjing.WCFService
{/// summary/// 对消息的管理/// /summarypublic class NoticeManager{public static ListNoticeInfo NoticeList new ListNoticeInfo();public static object m_SessionSyncRoot new object();public event AddHandler AddEvent null;private static NoticeManager instance;static NoticeManager() //类型构造器确保线程安全{instance new NoticeManager();}private NoticeManager() //构造方法为private,这就堵死了外界利用new创建此类型实例的可能{Thread.Sleep(50);//此处模拟创建对象耗时}public static NoticeManager GetInstance() //次方法是获得本类实例的唯一全局访问点{return instance;}/// summary/// 添加方法/// /summary/// param namenotice/parampublic void Add(NoticeInfo model){//后期再考虑消息的存储//foreach (var item in NoticeManager.NoticeList)//{// if (item.UserId model.UserId item.UserType model.UserType)// {// lock (NoticeManager.m_SessionSyncRoot)// {// NoticeManager.NoticeList.Remove(item);// }// }//}//lock (NoticeManager.m_SessionSyncRoot)//{// NoticeManager.NoticeList.Add(model);//}if (this.AddEvent ! null){this.AddEvent(model);}}}public delegate void AddHandler(NoticeInfo notice);} View Code 在MainService中注册委托 NoticeManager nm NoticeManager.GetInstance(); nm.AddEvent nm_AddEvent; IIS通过WCF发送消息 网站中引用WCF比较方便VS 中网站右键添加-》服务引用如下图 调用也非常简单两行代码 wcfnotice.UserNoticeServiceClient unsc new wcfnotice.UserNoticeServiceClient(); ///发订单 unsc.AddMessage(id, se, type, msg); 感谢 这篇文章写到一半时特别纠结觉得自己做的事件好像没有什么技术含量只是基于superSocket框架做了简单的应用一度想放弃这篇文章但转念一想我用这个程序替换原来的 SuperWebSocket后确实稳定了app任何时间都可以登录了也许能对那些正在和我们一样用SuperWebSocket的有所帮助也希望能共同交流。当然还有一个原因让我坚持写完了那就是对江大牛的感谢和敬佩也希望他能继续完善这个框架。 成为一名优秀的程序员 转载于:https://www.cnblogs.com/jijunjian/p/4049203.html