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 );
      }
  }
复制代码




本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2009/05/06/1451087.html,如需转载请自行联系原作者
目录
相关文章
|
6天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
16天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1317 7
|
4天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
285 128
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。
|
15天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1376 87
|
3天前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
4天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
261 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
5天前
|
弹性计算 安全 数据安全/隐私保护
2025年阿里云域名备案流程(新手图文详细流程)
本文图文详解阿里云账号注册、服务器租赁、域名购买及备案全流程,涵盖企业实名认证、信息模板创建、域名备案提交与管局审核等关键步骤,助您快速完成网站上线前的准备工作。
218 82
2025年阿里云域名备案流程(新手图文详细流程)