TopShelf框架创建Windows服务作为Remoting的宿主案例:
1.创建服务
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Topshelf; namespace YY.SmsPlatform.MassSendingSms { class Program { static void Main(string[] args) { HostFactory.Run(x => //1 { x.Service<MassSendingSms>(s => //2 { s.ConstructUsing(name => new MassSendingSms()); //3 s.WhenStarted(tc => tc.Start()); //4 s.WhenStopped(tc => tc.Stop()); //5 }); x.RunAsLocalSystem(); //6 x.SetDescription("大批量短信读取文件信息分包发送"); //7 x.SetDisplayName("MassSendingSmsService"); //8 x.SetServiceName("MassSendingSmsService"); //9 }); } } }
2.创建服务控制类型(这个类就是开始、暂停、继续、停止四个方法,本实例就开始与结束,开始代码内是创建了Remoting的远程访问对象)
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Text; using System.Threading.Tasks; using System.Configuration; using YY.SmsPlatform.Common.Host; namespace YY.SmsPlatform.MassSendingSms { public class MassSendingSms { public void Start() {
App.InitServiceObject(); //1. //2.Remoting服务器端激活(SingleCall) int tcpPort = Convert.ToInt32(ConfigurationManager.AppSettings["TcpPort"]); TcpChannel channel = new TcpChannel(tcpPort); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(MassSendingSmsModule), "MassSendingSmsServer", WellKnownObjectMode.SingleCall); channel.StartListening(new MassSendingSmsModule()); } public void Stop() { //获得当前已注册的通道; IChannel[] channels = ChannelServices.RegisteredChannels; //关闭指定名为MyTcp的通道; foreach (IChannel eachChannel in channels) { if (eachChannel.ChannelName == "MassSendingSmsServer") { TcpChannel tcpChannel = (TcpChannel)eachChannel; //关闭监听; tcpChannel.StopListening(null); //注销通道; ChannelServices.UnregisterChannel(tcpChannel); } } } } }
3.创建Remoting远程访问类(被访问):
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using YY.SmsPlatform.Common; using YY.SmsPlatform.Common.Data; using YY.SmsPlatform.Common.Host; using YY.SmsPlatform.Common.MassSendingSms; using YY.SmsPlatform.Common.Models; using YY.SmsPlatform.MassSendingSms.WebService; using System.Configuration; namespace YY.SmsPlatform.MassSendingSms { public class MassSendingSmsModule : MarshalByRefObject ,IMassSendingSmsModule { /// <summary> /// 获取数据源对象 /// </summary> public static IDataSource DataSource { get { return ObjectUtility.DataSource; } } //string userName, string password,DateTime? planSendTime,string Ip public Common.UserInterface.SendResult SendSms(int userId, string password, string mobile, string smsContent, DateTime? planSendTime, string iP) { var user = DataSource.GetUserInfo(userId);//获取客户其他信息 string totalId= System.Guid.NewGuid().ToString("N");//创建总ID DateTime totalTime=DateTime.Now; //1.验证 //2.短信拆分 var sms = new SmsObject() { Msisdns="", SMSContent=smsContent, PlanSendTime=null, ExtNumber=null, }; try { using (Stream inStream = new FileStream(mobile, FileMode.Open, FileAccess.Read)) using (StreamReader reader = new StreamReader(inStream, Encoding.Default)) { //TODO:生成一个总包的ID string strModile = "";//存储电话号码字符串 string line;//读取到的每一个字符串 int privateIntCountRecord = 0;//记录总包条数 //int count = 0;//记录分数量 int i = 0;//记录是否满足发送的条数 int partPackageParameter = 100;////100位分包大小,TODO:设置为后台参数 string webService = ConfigurationManager.AppSettings["WebServiceUrl"];//获取WebService请求地址 while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrWhiteSpace(line)) { strModile += line + ","; } privateIntCountRecord++; i++;//记录是否满足分包的条数,满足就发送 if (i == partPackageParameter)//达到数量提交 { //TODO:生成一个分包的id //count++;//第几个分包 //调用接口发送 WebService.WebService web = new WebService.WebService(); web.Url = webService;//TODO:在配置文件中设置 sms.Msisdns = strModile; DateTime submitTime = DateTime.Now; SendResult result = web.SendSms(user.UserName, password, sms); var parkPackage = new MASSSENDINGSMS_PARTOFPACKAGE() { Description = result.Description, Error = result.Errors.Join(","), PartPackageSize = partPackageParameter, PartSmsid = result.MsgId, Remark = "", StatusCode = result.StatusCode.ToString(), SubmitTime = submitTime, SuccessCount = result.SuccessCounts, TotalId = totalId, UserId = result.CustomId }; DataSource.InsertIntoMassSendingSmsPartPackage(parkPackage); //string a =result.StatusCode.ToString(); //将结果及统计数据写入数据库 i = 0; strModile = ""; Trace.TraceInformation("分包提交返回信息:Description(发送描述):" + result.Description + ",Error(错误描述):" + result.Errors.Join(",") + ",ParkPackageSize(分包大小):" + partPackageParameter + ",PartSmsId(分包Id):" + result.MsgId + ",StatusCode(返回状态码):" + result.StatusCode.ToString() + ",TotalId(总包ID):" + totalId + ",客户ID:" + userId + ",成功条数:" + result.SuccessCounts); } } if (!string.IsNullOrWhiteSpace(strModile))//最后如果不到分包量时提交一次,while和if中间最好不要插入代码 { var submitTime = DateTime.Now; //最后一个包发送 WebService.WebService web = new WebService.WebService(); web.Url = webService;//TODO:在配置文件中设置 sms.Msisdns = strModile; SendResult result = web.SendSms(user.UserName, password, sms); //将统计结果写入数据库 var parkPackage = new MASSSENDINGSMS_PARTOFPACKAGE() { Description = result.Description, Error = result.Errors.Join(","), PartPackageSize = privateIntCountRecord - partPackageParameter, PartSmsid = result.MsgId, Remark = "", StatusCode = result.StatusCode.ToString(), SubmitTime = submitTime, SuccessCount = result.SuccessCounts, TotalId = totalId, UserId = result.CustomId }; DataSource.InsertIntoMassSendingSmsPartPackage(parkPackage); strModile = ""; i = 0; Trace.TraceInformation("分包提交返回信息:Description(发送描述):" + result.Description + ",Error(错误描述):" + result.Errors.Join(",") + ",ParkPackageSize(分包大小):" + partPackageParameter + ",PartSmsId(分包Id):" + result.MsgId + ",StatusCode(返回状态码):" + result.StatusCode.ToString() + ",TotalId(总包ID):" + totalId + ",客户ID:" + userId+",成功条数:"+result.SuccessCounts); } var total = new MASSSENDINGSMS_TOTALOFPACKAGE() { SmsContent = sms.SMSContent, TotalId = totalId, TotalCount = privateIntCountRecord, TotalSubmitTime = totalTime, CustomerIp=iP }; //总包写入数据库 DataSource.InsertMassSendingSmsTotalPackage(total); Trace.TraceInformation("总包信息:TotalId(总包ID):" + totalId + ",SmsContent(发送内容):" + sms.SMSContent + ",TotalSubmitTime(总包提交时间):" + totalTime + ",客户Ip:" + iP+"总包条数:"+privateIntCountRecord); return new Common.UserInterface.SendResult() { StatusCode = Common.UserInterface.ResultCode.OK, Description = "具体发送结果请进行查询!" }; } } catch (Exception ex) { Trace.TraceInformation("大批量短信分包发送出现异常:"+ex); throw new Exception("分包发送发生异常:"+ ex); } } } }
4.Remoting客户端的实现:(此方法中的远程对象没有按照上面实例中写上,我实现的时候是远程对象实现了一个接口客户端创建的是一个远程接口对象)
TcpChannel channel = new TcpChannel(); ChannelServices.RegisterChannel(channel,false); RemotingConfiguration.RegisterWellKnownClientType(typeof(NetRemotingServer.ServerObject),"tcp://localhost:9001/ServerObject"); NetRemotingServer.ServerObject so = (NetRemotingServer.ServerObject)Activator.GetObject(typeof(NetRemotingServer.ServerObject), "tcp://localhost:9001/ServerObject");
5.自己实现的客户端远程对象,有自定义类型,所以也只能是示例不能运行(Remoting客户端通道注册)
#region MassSengdingSms(大批量短信发送远程对象) public static string WebMassSendingSmsUrl { get { var v = ConfigurationManager.AppSettings["WebMassSendingSmsUrl"]; if (v == null) { v = App.GetSetting("WebMassSendingSmsUrl"); } return v; } } private static readonly Lazy<IMassSendingSmsModule> massSendingModule= new Lazy<IMassSendingSmsModule>(()=> { var webMassSendingSmsUrl = WebObjectUtility.WebMassSendingSmsUrl; if (webMassSendingSmsUrl == null) throw new InvalidOperationException("未设置DataSourceUrl"); Trace.TraceInformation("WebMassSendingSmsUrl={0}", webMassSendingSmsUrl); IMassSendingSmsModule m = (IMassSendingSmsModule)Activator.GetObject(typeof(IMassSendingSmsModule), webMassSendingSmsUrl); return m; }); /// <summary> /// 获取远程大批量短信发送对象 /// </summary> public static IMassSendingSmsModule MassSendingSmsModule { get { return massSendingModule.Value; } } #endregion
6.完毕,简单的服务与Remoting远程访问创建