您的位置:首页 > 其它

ESFramework介绍之(28)―― Udp组件

2006-05-12 09:39 459 查看
ESFramework对Tcp和Udp协议都提供了完整的支持,在ESFramework介绍之(21)-- Tcp组件接口ITcp介绍ESFramework介绍之(23)―― AgileTcp 两篇文章中介绍了Tcp组件,相对于Tcp来说,Udp要简单许多,所以我在这里打算用一篇文章来介绍它。需要首先提出的是,ESFramework.Network命名空间下的所有直接类(即,不包括ESFramework.Network.Tcp和ESFramework.Network.Udp命名空间下的类)即可用于Tcp也可用于Udp。这中可复用性,将Tcp和Udp的区别仅仅隔离在最底层的通信组件中。

由于Udp组件相对简单,所以其实现策略与Tcp组件稍有不同,最主要的不同之处在于,Udp组件不需要分配器组件,而是直接将接收到消息转交给处理器工厂。大家应该还记得这个图:
EsbUdp
public class EsbUdp :IEsbUdp
{
private UdpClient udpClient ;
private int port = 10000;
private IContractHelper contractHelper ;
private INetMessageHook netMessageHook = new EmptyNetMessageHook();
private IDataDealerFactory dataDealerFactory ;

private volatile bool goToStop = true ;
private ManualResetEvent stopEvent = new ManualResetEvent(false) ;
public event CbServiceCommitted ServiceCommitted ;

public EsbUdp()
{
this.netMessageHook = new EmptyNetMessageHook() ;
}

public void Initialize()
{
this.udpClient = new UdpClient(this.port) ;
}

#region IEsbUdp 成员
public event CbInvalidMsg InvalidMsgRecieved ;

#region property
public int Port
{
set
{
this.port = value ;
}
}

public IContractHelper ContractHelper
{
set
{
this.contractHelper = value ;
}
}

public IDataDealerFactory DataDealerFactory
{
set
{
this.dataDealerFactory = value ;
}
}

public INetMessageHook NetMessageHook
{
set
{
if(value != null)
{
this.netMessageHook = value ;
}
else
{
this.netMessageHook = new EmptyNetMessageHook() ;
}
}
}
#endregion

#region Method
public void Start()
{
this.goToStop = false ;
this.stopEvent.Reset() ;
CbSimple cb = new CbSimple(this.Worker) ;
cb.BeginInvoke(null ,null) ;
}

public void Stop()
{
this.goToStop = true ;
//发送eof消息给自己,使Receive不再阻塞
byte[] eof = new byte[4] ;
this.udpClient.Send(eof ,4 ,new IPEndPoint(IPAddress.Parse("127.0.0.1") ,this.port)) ;

this.stopEvent.WaitOne() ;
}

public void HookAndSendNetMessage(IPEndPoint remoteIpe ,NetMessage msg)
{
byte[] data = this.netMessageHook.CaptureBeforeSendMsg(msg).ToStream() ;
this.udpClient.Send(data ,data.Length ,remoteIpe) ;
}

#region Worker
private void Worker()
{
while(! this.goToStop)
{
IPEndPoint remoteIPE = null ;
byte[] data = this.udpClient.Receive(ref remoteIPE ) ;
if(data.Length < this.contractHelper.MessageHeaderLength)
{
this.ActivateInvalidMsg(data ,remoteIPE) ;
continue ;
}

IMessageHeader header = this.contractHelper.ParseMessageHeader(data ,0) ;
if(((this.contractHelper.MessageHeaderLength + header.MessageBodyLength) > data.Length) || (! this.contractHelper.ValidateMessageToken(header)))
{
this.ActivateInvalidMsg(data ,remoteIPE) ;
continue ;
}

byte[] body = null ;
if(header.MessageBodyLength > 0)
{
body = new byte[header.MessageBodyLength] ;
for(int i=0 ;i<body.Length ;i++)
{
body[i] = data[this.contractHelper.MessageHeaderLength + i] ;
}
}

NetMessage msg = new NetMessage(header ,body) ;
msg.Tag = remoteIPE ;
NetMessage hookedMsg = this.netMessageHook.CaptureRecievedMsg(msg) ;

if(this.goToStop)
{
break ;
}

CbMessageDealing cb = new CbMessageDealing(this.MessageDealing) ;
cb.BeginInvoke(hookedMsg ,null ,null) ;
}

this.stopEvent.Set() ;
}

//异步处理消息
private void MessageDealing(NetMessage msg)
{
IDataDealer dealer = this.dataDealerFactory.CreateDealer(msg.Header.ServiceKey ,msg.Header.TypeKey) ;
NetMessage resMsg = dealer.DealRequestMessage(msg) ;

if(resMsg != null)
{
NetMessage hookedResMsg = this.netMessageHook.CaptureBeforeSendMsg(resMsg) ;
byte[] bRes = hookedResMsg.ToStream() ;
this.udpClient.Send(bRes,bRes.Length ,(IPEndPoint)msg.Tag) ;
if(this.ServiceCommitted != null)
{
this.ServiceCommitted(resMsg.Header.UserID ,hookedResMsg) ;
}
}
}

private void ActivateInvalidMsg(byte[] data ,IPEndPoint remoteIPE)
{
if(this.InvalidMsgRecieved != null)
{
this.InvalidMsgRecieved(data ,remoteIPE) ;
}
}
#endregion
#endregion

#endregion

}

public delegate void CbMessageDealing(NetMessage msg ) ;
关于ESFramework对Udp的支持,还有几个重要的主题需要介绍,除了上面提到的IUserManager组件,还有IUdpServerAgent组件(还记得ESFramework介绍之(7)-- 服务端代理IServerAgent),另外还有非常重要的一块--基于Udp的NAPT穿透。如果要了解这些内容,请继续关注本系列的文章。

上一篇:ESFramework介绍之(27)-- 支持OverdueMessage

转到 :ESFramework 可复用的通信框架(序)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: