TheONE--消息转发流程分析(3)

来源:http://blog.sina.com.cn/s/blog_48ded66a01018si3.html

TheONE--消息转发流程分析(3)

(2) 当消息不能直接到达目的节点时 

       在update函数中还有一个函数tryAllMessagesToAllConnections()专门负责处理类事件,他的优先级是要低于exchangeDeliverableMessages()的,也就是说当前节点如果有消息能够直接发送到目的节点,就应该优先发送。否则才会执行exchangeDeliverableMessages()函数,首先对所有的消息重新排序排序的函数仍是sortByQueueMode,在前面介绍过。最后,调用tryMessagesToConnections函数遍历排序之后的所有消息和所有连接,寻找能够发送的消息。

   protected Connection tryAllMessagesToAllConnections(){

      List connections = getConnections();

 

      if (connections.size() == 0 || this.getNrofMessages() == 0) {

          return null;

      }

 

      List messages =  new ArrayList(this.getMessageCollection());

      this.sortByQueueMode(messages);   //将所有的消息重新排序

 

      return tryMessagesToConnections(messages, connections);

   } 

在tryMessagesToConnections中,遍历所有的连接,然后调用tryAllMessages(con, messages)依次在每个连接上发送所有的消息。注意区别:在tryMessagesToConnections(messages, connections)中,messages指的是很多消息,connections指的是很多连接;而在tryAllMessages(con, messages)中,messages指的是很多消息,con指的是某个连接;然而在startTransfer(m, con)函数中,m是指某个消息,con是指某个连接。

       在tryAllMessages函数中,遍历所有的消息,依次尝试在con上能否发送成功,只要找到一个能发送的消息m,就终止该函数,返回消息m。否则尝试所有的消息都不能在con上发送,返回NULL。

   protected Message tryAllMessages(Connection con, List messages) {

      for (Message m : messages) {

          int retVal = startTransfer(m, con);

          if (retVal == RCV_OK) {

             return m;  // accepted a message, don't try others

          }

          else if (retVal > 0) {

             return null; // should try later -> don't bother trying others

          }

      }

      

      return null; // no message was accepted      

   } 

在发送消息的函数中,仍然执行的是startTransfer函数,startTransfer函数在前面已经介绍过了。

       到这里,EpidemicRouter中发送消息的流程已经介绍清楚了,EpidemicRouter路由中鼓励节点尽可能将所有的消息都转发给自己的邻居,因此只需要在ActiveRouter父类上做简单的扩展即可。接下的部分以其他路由为例研究一下路由协议是怎么扩展ActiveRouter的。

 

 

4.  路由扩展

 

(1)DirectDeliveryRouter

     这个路由的改法是最简单的,只需要在EpidemicRouter的基础上删除this.tryAllMessagesToAllConnections()函数,保留exchangeDeliverableMessages()函数即可,那么消息的转发流程中只剩下了第一部分。

 

(2)FirstContactRouter

EpidemicRouter是最简单的洪泛消息,其他路由协议与它最大的区别就在于:并不是所有的消息都照单全收。回忆上面的消息传输过程,无论是到目的节点还是到中间节点,都需要执行startTransfer,它负责在某个连接con上发送某个消息m。在这个函数中,首先找到con的另一端DTNHost然后调用receiveMessage函数查看对方能不能接收消息mreceiveMessage是一个不断被各种路由重载的函数,在MessageRouter中,实现了最基本的功能

① 将消息m放进IncomingBuffer;

② 当前节点存入消息m的Path中;

③ 通知所有的Listener发生了messageTransferStarted事件;

            在ActiveRouter中增加了功能:

④ 调用checkReceiving函数看对方节点能不能接收消息m,很多种可能都会导致消息不能被接收,在ActiveRouter中主要有:(1)对方节点正在发送消息,返回TRY_LATER_BUSY=1;(2)对方节点缓存中已经有该消息了,返回DENIED_OLD=-1;(3)消息超时,返回DENIED_TTL=-2;(4)对方节点缓存已满,返回ENIED_NO_SPACE=-3。

从上面的分析发现,要想消息按某种条件被转发,在checkReceiving函数中进行一些过滤是很合理的。

               FirstContactRouter路由中,区别在于节点把数据转发给第一次遇到的节点,然后就会将转发过的消息从缓存中删除。这里重载了checkReceiving函数。每次节点转发某个消息,都会将自己写在消息的path中,当节点发现自己已经处理过某个消息了,则会用DENIED_OLD的理由将其拒绝。需要指出的是顺序问题,将当前节点加入消息路径Path的操作是在receiveMessage中,这个操作是在checkReceiving之后,所以在检索path的时候当前节点还没有将自己写进Path

@Override

   protected int checkReceiving(Message m) {

      int recvCheck = super.checkReceiving(m);

      

      if (recvCheck == RCV_OK) {

          

          if (m.getHops().contains(getHost())) {

             recvCheck = DENIED_OLD;

          }

      }

      return recvCheck;

   }

       除此之外,FirstContactRouter还重载了transferDone函数。节点将消息发送成功之后就会清理缓存。这个函数在ActiveRouter中为空,在EpidemicRouter中也没有将其重载,所以在这里是第一次出现。

   @Override

   protected void transferDone(Connection con) {

      

      this.deleteMessage(con.getMessage().getId(), false);

   }

      在这里只是给出了两个路由协议最基本的例子,本文重点在于解释TheONE中消息转发的流程,因此其他的路由协议将在其他文章中进行分析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值