好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C# 小规模网络远程调用的基类(基于Socket方式)实现

C# 小规模网络远程调用的基类(基于Socket方式)实现

C# 小规模网络远程调用的基类(基于Socket方式)实现

一,程序逻辑图示 
 

物理拓扑就不画了,是一般简单的CS架构

二,服务端实现过程

  1), 服务端开始监听,并启动接收线程 
  

         public   void  Start( int  port)
        {
            _listenPort = port;
            serverSocket =  new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind( new  IPEndPoint(IPAddress.Any, port));
 
            serverSocket.Listen(_backlog);
            Console.WriteLine( "端口侦听开始" );
             for  ( int  i = 0; i < _recieveThreadCount; i++)
            {
                Thread acceptThread =  new  Thread( new  ThreadStart(RecieveAccept));
                acceptThread.Name =  "接收"  + (i + 1) +  "号线程" ;
                acceptThreadList.Add(acceptThread);
                acceptThread.Start();
            }
        }

  2), 接收线程的实现,按照上面的逻辑图示,我们接收到连接后,就要实例连接对象,并注入监听对象的服务对象 
 

            Console.WriteLine(Thread.CurrentThread.Name +  "开始" );
             while  ( true )
            {
                Socket clientSocket = serverSocket.Accept();
                _clientSocketList.Add( new  SocketClientBase(_instanceList, clientSocket));
                Console.WriteLine(Thread.CurrentThread.Name +  "获取到新的客户端("  + clientSocket.RemoteEndPoint.ToString() +  ")" );
            }

服务端的代码就这么多,所有操作都是交给连接对象(SocketClientBase)去处理的

三,客户端实现过程(连接对象)

1), 服务对象定义 

 [Serializable()]
     public   class  ObjectInstance
    {
         /// <summary> 
         /// 实例KEY 
         /// </summary> 
         public   string  InstanceKey { get; set; }
         /// <summary> 
         /// 实例 
         /// </summary> 
         public   object  Instance { get; set; }
    }

2), Request消息和Response消息的实现

    [Serializable()]
     abstract   public   class  Message
    {
         abstract   public  MessageType MessageType { get; set; }
    }
    [Serializable()]
     public   class  RequestMessage : Message
    {
         public  RequestMessage(ActionType actionType,  string  instanceKey,  string  callName)
        {
            _requestKey = Guid.NewGuid().ToString();
            ActionType = actionType;
            InstanceKey = instanceKey;
            CallName = callName;
        }
         private   string  _requestKey;
 
         public   string  RequestKey
        {
            get {  return  _requestKey; }
             private  set { _requestKey =  value ; }
        }
         public  DateTime SendTimeKey { get; set; }
         public  ActionType ActionType { get;  private  set; }
         public   string  InstanceKey { get;  private  set; }
         public   string  CallName { get;  private  set; }
         public   override  MessageType MessageType
        {
            get
            {
                 return  Net.MessageType.Request;
            }
            set
            {
                 throw   new  NotImplementedException();
            }
        }
 
         public  Object[] Parameters { get; set; }
    }
    [Serializable()]
     public   class  ResponseMessage : Message
    {
         public  ResponseMessage( string  requestKey)
        {
            _requestKey = requestKey;
        }
         private   string  _requestKey;
 
         public   string  RequestKey
        {
            get {  return  _requestKey; }
             private  set { _requestKey =  value ; }
        }
 
         public   bool  IsError { get; set; }
         public  XQException ErrorInfo { get; set; }
 
         public   object  ReturnObject { get; set; }
         public  DateTime SendTimeKey { get; set; }
 
         public   override  MessageType MessageType
        {
            get
            {
                 return  Net.MessageType.Response;
            }
            set
            {
                 throw   new  NotImplementedException();
            }
        }
    }
    [Serializable()]
     public   enum  ActionType
    {
        CallMethod = 0, CallProperty = 1, CallField = 4, Other = 8
    }
    [Serializable()]
     public   enum  MessageType
    {
        Response = 0, Request = 1
    }

上面我定义远程调用的方式的,和调用的约定对象,以及返回结果的定义

3),发送远程调用消息 
 

         /// <summary> 
         /// 调用远程方法 
         /// </summary> 
         /// <param name="instanceKey"></param> 
         /// <param name="methodName"></param> 
         /// <param name="pars"></param> 
         /// <returns></returns> 
         public  ResponseMessage CallRemoteMethod( string  instanceKey,  string  methodName,  params   object [] pars)
        {
            var response =  new  RequestMessage(ActionType.CallMethod, instanceKey, methodName);
             if  (pars !=  null  && pars.Length > 0)
                response.Parameters = pars;
             return  CallRemoteHost(response);
        }

  

         /// <summary> 
         /// 请求远程主机 
         /// </summary> 
         /// <param name="request"></param> 
         /// <returns></returns> 
         public  ResponseMessage CallRemoteHost(RequestMessage request)
        {
            ResponseMessage response =  null ;
            var getResponse =  new  OnGetReponseHandler( delegate (ResponseMessage args)
            {
                 if  (args.RequestKey == request.RequestKey)
                {
                    response = args;
                }
            });
             this .OnGetReponseEvent += getResponse;
            SendRequest(request);
            DateTime beginTime = DateTime.Now;
             while  ( true )
            {
                 if  (TimeSpan.FromTicks(DateTime.Now.Ticks - beginTime.Ticks).TotalMilliseconds > 60 * 1000)
                {
                     this .OnGetReponseEvent -= getResponse;
                     return   new  ResponseMessage(request.RequestKey) { IsError =  true , ErrorInfo = XQException.GetException(5565,  "远程操作超时" ) };
                }
                 if  (response !=  null )
                     break ;
            }
             this .OnGetReponseEvent -= getResponse;
             return  response;
        }

         /// <summary> 
         /// 发送请求 
         /// </summary> 
         /// <param name="request"></param> 
         private   void  SendRequest(RequestMessage request)
        {
             byte [] data = SerializationHelper.ToByte(request);
            var streamData = SetStreamDataEnd(data);
             int  count = clientSocket.Send(streamData);
            Console.WriteLine( "发送数据到"  + count +  "字节数据到"  + clientSocket.RemoteEndPoint.ToString());
        }

4), 回复远程调用,这里有两种情况,一种是远程主机发送过来的请求,另一种是远程主机响应的请求的回发 
a),消息为请求,我们就需要执行请求的内容,然后返回执行结果 
 

         private   void  ActionRequest(RequestMessage request)
        {
            ResponseMessage response =  new  ResponseMessage(request.RequestKey);
            Object instance = GetInstance(request.InstanceKey);
             if  (instance ==  null )
            {
                response.IsError =  true ;
                response.ErrorInfo = XQException.GetException(5566,  "实例不存在" );
            }
             else 
            {
                 string  callName = request.CallName;
                 switch  (request.ActionType)
                {
                     case  ActionType.CallMethod:
                        var methodInfo = instance.GetType().GetMethod(callName);
                         if  (methodInfo ==  null )
                        {
                            response.IsError =  true ;
                            response.ErrorInfo = XQException.GetException(5567,  "方法不存在" );
                        }
                         else 
                        {
                             object  result = methodInfo.Invoke(instance, request.Parameters);
                            response.ReturnObject = result;
                        }
                         break ;
                     case  ActionType.CallProperty:
                        var propertyInfo = instance.GetType().GetProperty(callName);
                         if  (propertyInfo ==  null )
                        {
                            response.IsError =  true ;
                            response.ErrorInfo = XQException.GetException(5568,  "属性不存在" );
                        }
                         else 
                        {
                             object  result = propertyInfo.GetValue(instance,  null );
                            response.ReturnObject = result;
                        }
                         break ;
                     case  ActionType.CallField:
                        var fieldInfo = instance.GetType().GetField(callName);
                         if  (fieldInfo ==  null )
                        {
                            response.IsError =  true ;
                            response.ErrorInfo = XQException.GetException(5569,  "字段不存在" );
                        }
                         else 
                        {
                             object  result = fieldInfo.GetValue(instance);
                            response.ReturnObject = result;
                        }
                         break ;
                }
            }
            SendResponse(response);
        }

b),当消息为返回的请求结果

        private   void  ActionResponse(ResponseMessage response)
        {
             if  (OnGetReponseEvent !=  null )
                OnGetReponseEvent(response);
        }

总结,这个实现模型,是基于一种旁注理念的,松耦合的实现方式,这个模型只是一个原型,没有错误处理等其他一些外围实现,我试验过单客户端IO性能大概48M,由于没有设计线程池,所以只能小规模应用

,完整源代码 /Files/Rolends/SocketBase.rar

转载请注明:http://www.cnblogs.com/Rolends  

    HAPPY EVERY DAY  ! !

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于C# 小规模网络远程调用的基类(基于Socket方式)实现的详细内容...

  阅读:53次