运用Smark.SocketAsyncs方便实现数据交互服务

 Smark.SocketAsyncs是通过SocketAsyncEventArgs对Socket进行包装的处理程序,暂时只封装了对Tcp的支持。以下是通过Smark.SocketAsyncs封装一个简单的数据交互服务。
1)制定基础数据传输描述
 实现消息转换适配器

 

代码

    
public   class  MessageAdapter:Smark.SocketAsyncs.IMessage
    {
        
public   object  Message
        {
            
get ;
            
set ;
        }
        
#region  IMessage 成员
        
public   void  SaveData(Encoding coding, Smark.SocketAsyncs.SendBuffer buffer)
        {
            buffer.Write(Smark.Core.Functions.SerializeObject(Message));
            buffer.WriteRN();
        }
        
public   void  LoadData(Encoding coding, Smark.SocketAsyncs.ReceiveBuffer buffer)
        {
            
byte [] data  =  buffer.ToBytes();
            Message 
=  Smark.Core.Functions.DeserializeObject(data);
        }
        
#endregion
    }

 

 

 适配器主要功能是对象和byte之前的转换.

 实现命令和返回类型描述

 

代码
    [Serializable]
    
public   class  Command
    {
        
        
public  CommandType Type
        {
            
get ;
            
set ;
        }
        
private  List < object >  mParameters  =   new  List < object > ();
        
public  List < object >  Parameters
        {
            
get
            {
                
return  mParameters;
            }
        }
        
public   object   this [ int  index]
        {
            
get
            {
                
return  Parameters[index];
            }
        }
        
    }
    
public   enum  CommandType
    {
        ListEmployee,
        LoadEmployee
    }
    [Serializable]
    
public   class  Result
    {
        
public   object  Data {  get set ; }
        
public   string  ErrorMessage {  get set ; }
    }

 

 

2)服务端代码实现
 建立一个控制台程序,定义相关监听对象和启用服务

 

代码
            Functions.LogOutputToConsole  =  LogType.Track;
            
string  dbstring  =   " Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " ;
            dbstring 
+=  Smark.Core.Functions.GetPath( typeof (Program).Assembly);
            dbstring 
+=   " Northwind.mdb " ;
            DBContext.SetConnectionString(ConnectionType.Context1, dbstring);
            TcpServer
< TcpClient < EofAtEnter >>  server  =   new  TcpServer < TcpClient < EofAtEnter >> ();
            server.ClientConnected 
+=  (o, e)  =>  {
                Functions.WriteLog(LogType.Track, 
typeof (Program),  " {0} On Connected \t {1} " , e.Client.Name,DateTime.Now);
            };
            server.ClientDisposed 
+=  (o, e)  =>  {
                Functions.WriteLog(LogType.Track, 
typeof (Program),  " {0} On Disposed \t {1} " , e.Client.Name,DateTime.Now);
            };
            server.ClientError 
+=  (o, e)  =>  {
                Functions.WriteLog(LogType.Track, 
typeof (Program),  " {0} On Error:{1} \t {2} " , e.Client.Name,e.Exception.Message, DateTime.Now);
            };
            server.ClientReceive 
+=  (o, e)  =>  {
                
try
                {
                   
                    Modules.Command cmd 
=  (Modules.Command)Functions.DeserializeObject(e.Buffer.Data, e.Buffer.Count  -   2 );
                    Execute(cmd,e.Client);
                }
                
catch  (Exception e_)
                {
                    Functions.WriteLog(LogType.Track, 
typeof (Program),  " {0} Data Error:{1} \t {2} " , e.Client.Name, e_.Message, DateTime.Now);
                    e.Client.Dispose();
                }
            };
            server.Open(Functions.AppSettingValue(
" ip " ),Functions.AppSettingValue < int > ( " port " ), 100 );
            Functions.WriteLog(LogType.Track, 
typeof (Program),  " SocketAsyncsForNorthwind.ServerApp Start \t {0} " ,DateTime.Now);
            Console.Read();

 

 

 以上是构建一个Tcp服务,并以/r/n作为结束分析协议。

 命令分发和处理代码

 

代码
         static   void  Execute(Modules.Command cmd,ITcpClient client)
        {
            StringBuilder sb 
=   new  StringBuilder();
            sb.AppendLine(
" Execute Command: "   +  cmd.Type);
            
foreach ( object  item  in  cmd.Parameters)
            {
                sb.AppendFormat(
" Parameter:{0}\r\n " , item);

            }
            
            Functions.WriteLog(LogType.Track, 
typeof (Program), sb.ToString());
            
switch  (cmd.Type)
            {
                
case  SocketAsyncsForNorthwind.Modules.CommandType.LoadEmployee:
                    LoadEmployee(cmd,client);
                    
break ;
                
case  SocketAsyncsForNorthwind.Modules.CommandType.ListEmployee:
                    ListEmployee(cmd, client);
                    
break ;

            }
        }
        
static   void  ListEmployee(Modules.Command cmd, ITcpClient client)
        {
            Modules.Result resul 
=   new  SocketAsyncsForNorthwind.Modules.Result();
            
try
            {
                Expression exp 
=   new  Expression();
                
if  (cmd.Parameters[ 0 !=   null )
                    exp 
&=  Modules.Employees.firstName.Match(cmd[ 0 ]);
                
if  (cmd[ 1 !=   null )
                    exp 
&=  Modules.Employees.lastName.Match(cmd[ 0 ]);
                
if  (cmd[ 2 !=   null )
                    exp 
&=  Modules.Employees.region.Match(cmd[ 0 ]);
                resul.Data 
=  exp.List < Modules.Employees > ();
            }
            
catch  (Exception e_)
            {
                resul.ErrorMessage 
=  e_.Message;
            }
            SendData(resul, client);
        }
         
        
static   void  LoadEmployee(Modules.Command cmd,ITcpClient client)
        {
            Modules.Result resul 
=   new  SocketAsyncsForNorthwind.Modules.Result();
            
try
            {
                Modules.Employees employee 
=  DBContext.Load < Modules.Employees > (cmd.Parameters[ 0 ]);
                resul.Data 
=  employee;
            }
            
catch  (Exception e_)
            {
                resul.ErrorMessage 
=  e_.Message;
            }
            SendData(resul, client);
           

        }
        
static   void  SendData( object  data, ITcpClient client)
        {
            Modules.MessageAdapter ma 
=   new  SocketAsyncsForNorthwind.Modules.MessageAdapter();
            ma.Message 
=  data;
            client.Send(ma);
        }

 


3)客户端实调用处理
 客户端逻辑包装类
 由于Smark.SocketAsyncs是基于异步处理的,所以为了方便调用封装一个基本同步发送和接放的包装类。

 

 

代码
public   class  NorthWindClient:IDisposable
    {

        
private  System.Threading.EventWaitHandle mHandler  =   new  System.Threading.EventWaitHandle( false , System.Threading.EventResetMode.ManualReset);
        
private  TcpClient < EofAtEnter >  mClient;
        
public  NorthWindClient( string  ip,  int  port)
        {
            Init(ip, port);
        }
        
private   void  Init( string  ip, int  port)
        {
            mClient 
=  TcpServer < TcpClient < EofAtEnter >> .CreateClient(ip, port);
            mClient.Receive();
            mClient.Error 
+=  (o, e)  =>  {
                Result 
=   new  Result();
                Result.ErrorMessage 
=  e.Exception.Message;
                mHandler.Set();
            };
            mClient.DataReceive 
+=  (o, e)  =>  {
                
byte [] data  =  e.Buffer.ToBytes( 0 , e.Buffer.Count  -   2 );
                Result 
=  (Modules.Result)Functions.DeserializeObject(data);
                mHandler.Set();
            };
        }
        
public  Result Result
        {
            
get ;
            
set ;
        }
        
public  IList < Employees >  ListEmployees( string  firstname,  string  lastname,  string  region)
        {
            Result 
=   null ;
            Modules.Command cmd 
=   new  Command();
            cmd.Type 
=  CommandType.ListEmployee;
            cmd.Parameters.Add(firstname);
            cmd.Parameters.Add(lastname);
            cmd.Parameters.Add(region);
            
return  (IList < Employees > )SendData(cmd);
        }
        
public  Employees LoadEmployee( int  id)
        {
            Result 
=   null ;
            Modules.Command cmd 
=   new  Command();
            cmd.Type 
=  CommandType.LoadEmployee;
            cmd.Parameters.Add(id);
           
return  (Employees) SendData(cmd);
           
           

        }
        
protected   object  SendData( object  data)
        {
            
return  SendData(data,  2000 );
        }
        
protected   object  SendData( object  data, int  timeout)
        {
            Modules.MessageAdapter ma 
=   new  MessageAdapter();
            ma.Message 
=  data;
            mClient.Send(ma);
            mHandler.Reset();
            mHandler.WaitOne(timeout);
            
if  (Result  ==   null )
            {
                
throw   new  Exception( " 超时! " );
            }
            
else   if  (Result.ErrorMessage  !=   null )
            {
                
throw   new  Exception(Result.ErrorMessage);
            }
            
return  Result.Data;
        }
        
#region  IDisposable 成员

        
public   void  Dispose()
        {
            
if  (mClient  !=   null )
                mClient.Dispose();
        }

        
#endregion
    }

 

 NorthWindClient功能在初始化的时候接入的服务器,每个逻辑在请求时挂起2秒等待处理,处理错误或超时返回异常。当接收到服务端处理完后取消挂起返回处理值。

 客户端UI处理代码


代码
     public   partial   class  Form1 : Form
    {
        
private  Modules.NorthWindClient Client;
        
public  Form1()
        {
            InitializeComponent();
        }

        
private   void  Form1_Load( object  sender, EventArgs e)
        {
            
try
            {
                Smark.SocketAsyncs.Utils.AsyncEventArgsPool_MAX 
=   10 ;
                Client 
=   new  SocketAsyncsForNorthwind.Modules.NorthWindClient(Functions.AppSettingValue( " ip " ), Functions.AppSettingValue < int > ( " port " ));
                dataGridView1.DataSource 
=  Client.ListEmployees( null null null );
            }
            
catch  (Exception e_)
            {
                MessageBox.Show(e_.Message);
            }
        }


        
private   void  dataGridView1_SelectionChanged( object  sender, EventArgs e)
        {
            
if  (dataGridView1.SelectedRows.Count > 0 )
            {
                Modules.Employees emp 
=  (Modules.Employees)dataGridView1.SelectedRows[ 0 ].DataBoundItem;
                propertyGrid1.SelectedObject 
=  Client.LoadEmployee(emp.EmployeeID);
            }
        }

        
private   void  button1_Click( object  sender, EventArgs e)
        {
            
try
            {
            dataGridView1.DataSource 
=  Client.ListEmployees(textBox1.Text, textBox2.Text, textBox3.Text);
            }
            
catch  (Exception e_)
            {
                MessageBox.Show(e_.Message);
            }
        }      
    }

 

相关程序代码:[url:https://smark.svn.codeplex.com/svn/Samples/SocketAsyncsForNorthwind/]

4)简单负载测试

  测试用例获取所有Employee数据

 

你可能感兴趣的:(运用Smark.SocketAsyncs方便实现数据交互服务)