• 跨平台开源通讯组件elastic communication


        elastic communication是基于c#开发支持.net和mono的通讯组件(简称EC),EC的主要目的简化mono和.net下的通讯开发难度,通过EC可以非常快速地开发基于mono和.net的通讯交互应用。EC抽取的基础的通讯协议默认支持protobuf,msgpack的数据对象进行通讯交互,开发者不可以根据自己的制要制订更多的序列化方式支持;EC不紧紧支持简单的对像传输,还提供了控制器,方法控制器和更方便的远程接口调用功能。

        以下是ES希望实现的最终目标

        

        借助于Xamarin实现不同移动端的实现,由于这一块个人工作原因还没细化实现,通过开源相关代码可以让感兴趣的人更好进一步去完成相关功能。

    功能简介

        EC实现通讯功能是非常方便的事情,下面通讯简单的几种场景来介绍一下EC在通讯上的应用。

    HelloWord

    • 服务端
      namespace HelloWord.Server
      {
          [Controller]
          public class Program
          {
              static void Main(string[] args)
              {
                  ECServer.Open();
                  System.Threading.Thread.Sleep(-1);
              }
      
              public string HelloWord(ISession session,Hello e)
              {
                  return string.Format("hello {0} [say time:{1}]", e.Name, DateTime.Now);
              }
          }
      
          [MessageID(0x1)]
          [ProtoContract]
          public class Hello
          {
              [ProtoMember(1)]
              public string Name { get; set; }
          }
      }
    • 客户端
      private EC.ProtoSyncClient mClient = new ProtoSyncClient("127.0.0.1");
      mClient.Send<string>(new Hello { Name=textBox1.Text })

    远程方法访问

      EC支持远程方法调用,如果用过wcf那对这功能感觉应该不会陌生,而EC也是通过接口的方式来定义远程调用行为;wcf同一方法重载需要重新定义名称,而ec则支持同一方法多个重载版本。为了满足更复杂的需要,EC的远程调用同样支持out和ref参数。

    • 接口定义
      namespace Remoting.Service
      {
          public interface IUserService
          {
              User Register(string name, string email);
          }
      }
    • 服务端
      [SOAService(typeof(Service.IUserService))]
          class Program : IUserService
          {
              static void Main(string[] args)
              {
                  ECServer.Open();
                  System.Threading.Thread.Sleep(-1);
              }
      
              public Service.User Register(string name, string email)
              {
                  User user = new User();
                  user.EMail = email;
                  user.Name = name;
                  user.CreateTime = DateTime.Now;
                  return user;
              }
          }
    • 客户端
        public partial class Form1 : Form
          {
              public Form1()
              {
                  InitializeComponent();
              }
      
              private ProtoClient mClient = new ProtoClient("192.168.7.111");
      
              private IUserService UserService;
      
              private void Form1_Load(object sender, EventArgs e)
              {
                  UserService = mClient.CreateInstance<IUserService>();
              }
      
              private void cmdRegister_Click(object sender, EventArgs e)
              {
                  User user= UserService.Register(txtName.Text, txtEMail.Text);
                  txtCreateTime.Text = user.CreateTime.ToString();
              }
          }

    数据访问示例

       数据访问应该是最常见的一种应用场,以下是定义一个简单的数据查询示例。

    • 服务端
       [EC.Controller]
          public class Program
          {
              static void Main(string[] args)
              {
                  DBContext.SetConnectionDriver<SqliteDriver>(DB.DB1);
                  DBContext.SetConnectionString(DB.DB1, "Data Source=northwindEF.db;Pooling=true;FailIfMissing=false;");
                  ECServer.Open();
                  System.Threading.Thread.Sleep(-1);
              }
      
              public IList<Employee> OnEmployeeSearch(ISession session, EmployeeSearch e)
              {
                  return new Expression().List<Models.Employees, Employee>();
              }
      
              public IList<Customer> OnCustomerSearch(ISession session, CustomerSearch e)
              {
                  return new Expression().List<Models.Customers, Customer>();
              }
      
              public IList<Order> OnOrderSearch(ISession session, OrderSearch e)
              {
                  Expression exp = new Expression();
                  if (e.CustomerID != null)
                      exp &= Models.Orders.customerID == e.CustomerID;
                  if (e.EmployeeID > 0)
                      exp &= Models.Orders.employeeID == e.EmployeeID;
                  return exp.List<Models.Orders, Order>();
              }
      
              public IList<OrderDetail> GetOrderDetail(ISession session, GetDetail e)
              {
                  Expression exp = Models.OrderDetails.orderID == e.OrderID;
                  JoinTable jt = Models.OrderDetails.productID.InnerJoin(Models.Products.productID);
                  jt.Select("OrderDetails.*", Models.Products.productName.Name);
                  return exp.List<OrderDetail>(jt);
              }
      
          }
    • 客户端
      private ProtoSyncClient mClient = new ProtoSyncClient("127.0.0.1");
      
              private void FrmMain_Load(object sender, EventArgs e)
              {
                  cbEmployees.Items.Add(new Employee());
                  foreach (Employee item in mClient.Send<IList<Employee>>(new EmployeeSearch()))
                  {
                      cbEmployees.Items.Add(item);
                  }
                  cbCustomers.Items.Add(new Customer());
                  foreach (Customer item in mClient.Send<IList<Customer>>(new CustomerSearch()))
                  {
                      cbCustomers.Items.Add(item);
                  }
                  
              }
      
              private void cmdSearch_Click(object sender, EventArgs e)
              {
                  OrderSearch os = new OrderSearch();
                  if (cbCustomers.SelectedItem != null)
                      os.CustomerID = ((Customer)cbCustomers.SelectedItem).CustomerID;
                  if (cbEmployees.SelectedItem != null)
                      os.EmployeeID = ((Employee)cbEmployees.SelectedItem).EmployeeID;
                  gdOrder.DataSource = mClient.Send<IList<Order>>(os);
              }
      
              private void gdOrder_SelectionChanged(object sender, EventArgs e)
              {
                  if (gdOrder.SelectedRows.Count > 0)
                  {
                      Order order = (Order)gdOrder.SelectedRows[0].DataBoundItem;
                      GetDetail getdetail = new GetDetail();
                      getdetail.OrderID = order.OrderID;
                      gdDetail.DataSource = mClient.Send<IList<OrderDetail>>(getdetail);
                  }
              }

    AppModule

         AppModule类似于asp.net的httpModule,它可以在EC服务中载实始化的时候进行加载,通过AppModule可以实现消息处理,处理日志,全局信息定义等相关主要功能。

        public class FilterModel : IAppModel
        {
    
            public string Name
            {
                get { return "Filter"; }
            }
    
            private System.Threading.Timer mTimer;
    
            public void Init(IApplication application)
            {
                //application.Filters.Add(new LoginFilter());
                application.Disconnected += (o, e) =>
                {
                    "{0} disposed applicaion event".Log4Info(e.Session.Channel.EndPoint);
    
                };
                application.Connected += (o, e) =>
                {
    
                    "{0} connect applicaion event".Log4Info(e.ChannelConnectArgs.Channel.EndPoint);
    
                };
                  application.SendCompleted += (o, e) =>
                  {
                     "{0} send completed applicaion event".Log4Info(e.Session.Channel.EndPoint);
                  };
                 application.MethodProcess += (o, e) =>
                 {
                     //application
                     e.Application["Path"] = @"c:";
                     //sexxion
                     e.Session["folder"] = "aaa";
                 };
                application.Error += (o, e) =>
                {
                    "{0} channel error {1}".Log4Error(e.Info.Channel.EndPoint, e.Info.Error.Message);
                };
                mTimer = new System.Threading.Timer(o =>
                {
                    application.Server.Send(new User { Name = Guid.NewGuid().ToString("N"),CreateTime = DateTime.Now }, application.Server.GetOnlines());
                }, null, 1000, 1000);
    
            }
            public string Command(string cmd)
            {
                throw new NotImplementedException();
            }
        }

    Filter

        这个特性在EC上是提供比较有用的功能,通讯filter可以对调用方法加入权限,日志,拦载等逻辑功能。  

    public class AdminFilter : FilterAttribute
        {
            public override void Execute(IMethodContext context)
            {
                "admin filter ->{0}".Log4Debug(context.Handler);
                base.Execute(context);
            }
        }
        [Controller]
        public class Controller
        {
            [SkipFilter(typeof(LoginFilter))]
            [ThreadPool]
            public User Regisetr(ISession session, User user)
            {
                user.CreateTime = DateTime.Now;
                "Register invoke[Name:{0} Email:{1}]".Log4Debug(user.Name, user.EMail);
    
                return user;
            }
    
            [AdminFilter]
            public IList<User> Search(ISession session, Query query)
            {
                "Search invoke".Log4Debug();
                List<User> users = new List<User>();
                users.Add(new User());
                users.Add(new User());
                return users;
            }
        }

    开源地址

      https://github.com/IKende/ec/

      https://github.com/IKende/ec/tree/master/Samples

    开源原因

        其实我个人不太多喜欢走开源路线,主要是工作和手头上的一些产品太多,而这个产品可以说完善度已经达到90%,如果扔在那里感觉有点可惜了,所以把产品开源出来,如果有兴趣的朋友可以复制完善它。

  • 相关阅读:
    The server must be started under an unprivileged user ID to prevent
    it starts (“forks”) a new process for each connection.
    kong
    flume采集微信小程序数据
    bc
    LINUX上一个命令计算PI
    parameters arguments 形式参数 实际参数
    极限编程 简单设计
    Communicating sequential processes CSP 通信顺序进程 CSP writing to a file by name (process, Erlang) vs. writing to a file descriptor (channel, Go)
    hcitool
  • 原文地址:https://www.cnblogs.com/smark/p/5007019.html
Copyright © 2020-2023  润新知