根据源码研究Tigase内部处理机制

1、打开Tiagse源码,TigaseServer启动入口 start方法:


String config_class_name = System.getProperty( CONFIGURATOR_PROP_KEY,DEF_CONFIGURATOR );

			config = (ConfiguratorAbstract) Class.forName( config_class_name ).newInstance();
			config.init( args );

			// config = new ConfiguratorOld(config_file, args);
			config.setName( "basic-conf" );

			String mr_class_name = config.getMessageRouterClassName();
			router = (MessageRouterIfc) Class.forName( mr_class_name ).newInstance();

			router.setName( serverName );
			router.setConfig( config );//初始化組件
			router.start();//启动Server



1.1 分析MessageRouter类


    说明:主要任务就是根据配置文件搜集所有的组件,构建XMPP路由服务环境;

MessageRouter.java

@Override
public void setConfig(ConfiguratorAbstract config) {
   components.put(getName(), this);//将自身添加到自己的components成员变量
   this.config = config;
   addRegistrator(config);//将自身注册进组件列表中,注意*registrators map类型。存放所有的组件
 }
public void addRegistrator(ComponentRegistrator registr) {
	registrators.put(registr.getName(), registr);//将自身注册到registrators表中
	addComponent(registr);//将registr注册到components中
	for (ServerComponent comp : components.values()) {
	    registr.addComponent(comp);
	  }   
	}



A:addRegistrator();//获取所有可以连接到MesssageRouter的ServerComponent


B:addComponent(registr) ;//汇集registr中的组件

C:registr.addComponent(comp);//注册所有组件

1.2、组件的初始化

通过setProperties(Map<String, Object> props)方法完成组件的初始化。

过程:1、分离出所有的组件如果组件instances MessageReceiver(可以接收数据包)那么则添加到组件路由。

         2、组件初始化完毕。调用comp.initializationCompleted();方法

2、ClientConnectionManager处理客户端发送过来的数据包的过程如下图

整个处理流程如下:

2.1.socket监听接收客户端报文

socket接收到tcp报文然后转换为xmpp packet的过程;

主处理组件:ClientConnectionManager

c2s在启动的时候创建了3类线程(创建过程参考启动篇):

socketReadThread():负责读socket的数据;

socketWriteThread():负责向socket写数据;

ResultsListener:负责componet执行结果的处理;

a.socketReadThread和socketWriteThread循环selector.select(),得到selectionKey->XMPPIOService放到队列等待完成。

b.等待完成的XMPPIOService,通过completionService.submit(serv)提交执行,调用XMPPIOService.call();

c.XMPPIOService.call(),完成了接收的socket报文到packet,作为packet在内部处理的入口(后面介绍这些处理);

d.ResultsListener根据XMPPIOService.call()返回的XMPPIOService对象,如果对象不为空重新放回到waiting列表(用于重新注册到clientsSel(selector));

2.2.组件对packet的处理过程


 a.从XMPPIOService.call();

processSocketData();
if ((receivedPackets() > 0) && (serviceListener != null)) {
  /**
    *serviceListener 这里是clientConnectManager;在connectionOpenTrhead里      设置
    **/
  serviceListener.packetsReady(this);
}

b.processSocketData()把报文转成xml element;再把element转成对应的packet;

while ((elem = elems.poll()) != null) {
  //Message、Presence、IQ、其他Packet
  Packet pack = Packet.packetInstance(elem);
  addReceivedPacket(pack); sendAck(pack);//ack 模式,收到后发送ack
}

c.serviceListener.packetsReady()---->ClientConnectManager.packetsReady()---->processSocketData([此时设置了packet的to和from属性,在messagerouter中决定由那个组件处理])---->addOutPacket(packet)---->放到c2s的输出队列中;

d.c2s中的输出消息队列由QueueListener线程来读取处理;

if ((packet = filterPacket(packet, outgoing_filters)) != null) {
    //out_filter处理	
    processOutPacket(packet);
}



e. processOutPacket () 默认此方法只在queue中进行packet复制


if (parent != null) {
    //parent指message_router,在初始化的时候设置
     parent.addPacket(packet);//传递给clientConnectManager,把packet构建完成后,交给messageRouter 来处理,添加到它的in_queue;
   } else {
     // It may happen for MessageRouter and this is intentional
     addPacketNB(packet);
}



f.MessageRouter对in_queue里的packet,通过QueueListener线程调messageRouter.processPacket()轮训。

//根据to属性,查找local的component,普通聊天,一般是路由到SessionManager组件
ServerComponent comp = getLocalComponent(packet.getTo());
	if (comp != null) {
		if (log.isLoggable(Level.FINEST)) {
			log.log(Level.FINEST, "1. Packet will be processed by: {0}, {1}", new Object[] {
						comp.getComponentId(),
						packet });
			}

			Queue<Packet> results = new ArrayDeque<Packet>();
			if (comp == this) {
				processPacketMR(packet, results);
			} else {
				comp.processPacket(packet, results);
			}
			if (results.size() > 0) {
				for (Packet res : results) {
					addOutPacketNB(res);

					
				} 
			}
			return;
		}

		String            host  = packet.getTo().getDomain();
		ServerComponent[] comps = getComponentsForLocalDomain(host);

		if (comps == null) {
			comps = getServerComponentsForRegex(packet.getTo().getBareJID().toString());
		}
		if ((comps == null) &&!isLocalDomain(host)) {
			comps = getComponentsForNonLocalDomain(host);
		}
		if (comps != null) {
			Queue<Packet> results = new ArrayDeque<Packet>();

			for (ServerComponent serverComponent : comps) {
				if (log.isLoggable(Level.FINEST)) {
					log.log(Level.FINEST, "2. Packet will be processed by: {0}, {1}",
							new Object[] { serverComponent.getComponentId(),
							packet });
				}
				serverComponent.processPacket(packet, results);
				if (results.size() > 0) {
					for (Packet res : results) {
						addOutPacketNB(res);
					}  
				}
			}
		} else {
			if (log.isLoggable(Level.FINEST)) {
				log.finest("There is no component for the packet, sending it back");
			}
			try {
				addOutPacketNB(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet,
						"There is no service found to process your request.", true));
			} catch (PacketErrorTypeException e) {
				log.warning("Can't process packet to local domain, dropping..." + packet
						.toStringSecure());
			}
		}

3、SessionManager对packet的处理,如下图,就不多说了






转载于:https://my.oschina.net/wjwei113/blog/369784

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值