Azureus源码剖析(三)

      接着第一篇的工作,本篇继续分析种子文件监听服务器的实现细节。

先简单描述下其工作流程,首先服务器在6880端口处开启一个套接字监听,然后开启一个守护线程用于处理到来的打开种子文件列表请求,在这个服务线程中不断循环读取来自客户的请求,对torrent文件列表进行解析。如果此时Azureus的各个组件都已经创建完毕,则说明Azureus的核心处理组件可用,则直接对torrent文件列表进行处理,否则,先将torrent文件列表加入种子文件队列中,等到各个组件创建完毕后再来处理种子队列中的各个种子文件。

下面来查看其源代码,先看其成员变量:

private  ServerSocket socket; // 服务器套接字
     private   int  state; // 服务器当前状态
     private   boolean  bContinue; // 服务线程是否继续运行
     public   static   final   int  STATE_FAULTY  =   0 ; // 错误状态
     public   static   final   int  STATE_LISTENING  =   1 ; // 监听状态
     protected  List queued_torrents  =   new  ArrayList(); // 待解析种子文件队列,这里并没有考虑同步互斥的问题
protected   boolean  core_started     =   false ; // 核心处理组件是否已经启动

在其构造函数中完成服务器的创建和启动:

            socket  =   new  ServerSocket( 6880 50 , InetAddress.getByName( " 127.0.0.1 " ));  // NOLAR: only bind to localhost
        
            state 
=  STATE_LISTENING; // 设置服务器状态为“监听”

而在pollForConnections中为Azureus添加了一个生命周期监听器,这样当其所有组件完成时就会通知此监听器,而后者会调用openQueuedTorrents方法,对待解析种子文件队列中排队的种子文件进行处理,此外,这个方法中还创建了一个守护线程用于处理到来的打开种子文件列表请求,实际的处理工作在pollForConnectionsSupport方法中完成:

     public   void  pollForConnections( final  AzureusCore azureus_core )
    {
        
// 增加生命周期监听者
        azureus_core.addLifecycleListener( new  AzureusCoreLifecycleAdapter()
        {
            
// 所有组件创建完毕
             public   void  componentCreated(AzureusCore core, AzureusCoreComponent    component) 
            {
                
if  ( component  instanceof  UIFunctionsSWT )
                {
                    openQueuedTorrents( azureus_core );
// 打开排队的种子文件列表
                }
            }
        });
        
        
if  ( socket  !=   null  )
        {
// 开启一个守护线程用于处理到来的打开种子文件列表请求
            Thread t  =   new  AEThread( " Start Server " )
            {
                
// runSupport是一个abstract方法,在run中调用,是实际的线程函数
                 public   void  runSupport()
                {
                    pollForConnectionsSupport( azureus_core );
                }
            };
            t.setDaemon(
true );
            t.start(); 
// 启动线程
        }
    }

这里线程的中断采用设置运行标志的方式,我觉得这并不是一个很好的解决方案,因为若线程要完成的工作十分耗时,则线程的中断就不能立即见效。更好的办法应该是interrupt方法和中断标志混合起来使用。

 

private   void  pollForConnectionsSupport(AzureusCore azureus_core) 
  {
      bContinue 
=   true ;
      
while  (bContinue) 
      {
          BufferedReader br 
=   null ;
          
try  
          {
              Socket sck 
=  socket.accept(); // 接受一个连接请求
              String address  =  sck.getInetAddress().getHostAddress();  // 绑定的本地IP地址
               if  (address.equals( " localhost " ||  address.equals( " 127.0.0.1 " )) 
              {
                  br 
=   new  BufferedReader( new  InputStreamReader(sck.getInputStream(),Constants.DEFAULT_ENCODING));
                  String line 
=  br.readLine(); // 读取一行数据          
                   if  (Logger.isEnabled())
                        Logger.log(
new  LogEvent(LOGID,  " Main::startServer: received ' " +  line  +   " ' " ));
                  
if  (line  !=   null )
                  {
                      String [] args 
=  parseArgs(line); // 解析请求数据
                       if  (args  !=   null   &&  args.length  >   0
                      {
                          String debug_str 
=  args[ 0 ]; // 第一行数据仅供测试使用,故抛弃不用
                           for  ( int  i = 1 ; i < args.length; i ++
                          {
                              debug_str 
+=   "  ;  "   +  args[i];
                          }
                          Logger.log(
new  LogEvent(LOGID,  " Main::startServer: decoded to ' "   +  debug_str  +   " ' " ));
                          processArgs(azureus_core,args); 
// 处理解析出的种子文件列表

                      }
                  }
              }
              sck.close();
          }
          
catch  (Exception e) 
          {
              
if ( ! (e  instanceof  SocketException))
                  Debug.printStackTrace( e );      
          }
          
finally  
          {
              
try  
              {
                  
if  (br  !=   null )
                      br.close();
              } 
catch  (Exception e) {  /* ignore  */ }
          }
      }
  }

      在种子文件列表解析成功后,对其处理要分情况考虑,若处理核心还未启动,则将其加入种子队列中排队等待,否则直接对其解析处理。

try  
        {
            this_mon.enter();

            
if  ( ! core_started) 
            {
// 若核心还未启动,则进入种子队列中等待
                queued_torrents.add(  new  Object[]{ file_name,  new  Boolean( open )}); // 加入种子文件队列中
                queued  =   true ;
            }
        }
        
finally  
        {
          this_mon.exit();
        }
        
if  (  ! queued )
        {
// 无须排队,直接进行种子文件的解析处理
            handleFile( azureus_core, file_name, open );
        }

      具体的处理工作由handleFile完成,其中调用了openTorrent方法来打开种子文件,具体的种子文件解析见第二文章

   protected   void  handleFile(AzureusCore    azureus_core,String file_name, boolean  open )
  {
// 处理种子文件
       try  
      {
          
if  ( open )
          {
              TorrentOpener.openTorrent(file_name);
// 打开种子文件
              
          }
          
else
          {
              File    f 
=   new  File( file_name );
              
if  ( f.isDirectory())
              {
                  ShareUtils.shareDir( azureus_core, file_name );
                  
              }
              
else
              {
                 ShareUtils.shareFile( azureus_core, file_name );                     
              }
          }
      } 
      
catch  (Throwable e)
      {
        Debug.printStackTrace(e);
      }
  }

      当Azureus生命周期来到各个组件都创建完毕时,会通知其监听者,从而调用 openQueuedTorrents方法来处理排队中的种子文件

protected   void  openQueuedTorrents(AzureusCore azureus_core )
  {
      
try
      {
          this_mon.enter();
          core_started    
=   true ; // 核心启动!
      }
      
finally
      {
          this_mon.exit();
      }
         
      
// 处理种子队列中的种子文件
       for  ( int  i = 0 ;i < queued_torrents.size();i ++ )
      {
          Object[]    entry 
=  (Object[])queued_torrents.get(i);
          String    file_name     
=  (String)entry[ 0 ]; // 种子文件名
           boolean     open         =  ((Boolean)entry[ 1 ]).booleanValue(); // 是否已经打开
          handleFile( azureus_core, file_name, open );
      }
  }

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值