且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

基于Mozilla Thunderbird的扩展开发(五)---进程间通信之Socket篇(上)

更新时间:2022-09-14 15:16:39

      这个系列的前两篇文章主要是根据自己的需求,对Thunderbird的源代码进行修改,改进了Thunderbird的现有功能,关注点都在Thunderbird的老本行---邮件客户端的实现上,那是否Thunderbird就仅仅是一个邮件客户端呢?在我看来,并非如此,它源自Mozilla内核,就继承了Mozilla平台的光荣传统,应该视为一个优秀的可扩展的开发平台,更进一步来看,Mozilla的文化深入其骨髓,可以看到后来Adobe的Flex,MicroSoft的WPF都吸收了Mozilla平台界面与逻辑相分离的思想,所以接下来几篇文章我想写一个比较有意思的方面----进程间通信。
      进程间通信的概念在操作系统中有过详细的介绍,方法很多,我主要关注其中两种:socket通信,Pipe(管道)通信。
      本文的目的就是开发一个扩展,展示TCP/IP socket技术在Mozilla扩展开发中的应用。
服务器端主代码:
  const tBirdBiffServerUi =
  {
    tBirdBiffServerOnLoad: function()
    {//启动服务器
      // remove to avoid duplicate initialization
      removeEventListener("load", tBirdBiffServerUi.tBirdBiffServerOnLoad, true);
      tBirdBiffCommon.setIconPosition();//设置图标位置
    //创建服务器对象并初始化
      var server = Components.classes["@phinecos.cnblogs.com/TBbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
      server.initialize();
      server.addWindow(window);//保存当前窗口
      server = null;
    },
    tBirdBiffServerOnClose: function()
    {//关闭服务器
      // remove to avoid duplicate initialization
      removeEventListener("close", tBirdBiffServerUi.tBirdBiffServerOnClose, true);

    //移除当前窗口
      var server = Components.classes["@dpwhite.com/thunderbirdbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
      server.removeWindow(window);
      server = null;
    }
  }

  addEventListener("load", tBirdBiffServerUi.tBirdBiffServerOnLoad, true);
  addEventListener("close", tBirdBiffServerUi.tBirdBiffServerOnClose, true);


服务器类,负责创建服务器端socket,并异步监听来自客户端的请求,管理邮箱状态的变化和来自客户端的连接。
服务器类

服务器监听类,负责监听来自客户端的各个请求:
function tBirdBiffServerConnection()
{
  this.wrappedJSObject = this;
}

tBirdBiffServerConnection.prototype =
{
  socket: null,//客户端对应的socket
  outputStream: null,//输出流

  setSocket: function(value)
  {//保存来自客户端的socket连接
    try
    {
      this.outputStream = value.openOutputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 0, 0);//打开输出流,类型为阻塞型,无缓冲区
    }
    catch(e)
    {
       return false;
    }
    if(!this.outputStream)
    {
      return false;
    }
    this.socket = value;
    return true;
  },

  closeSocket: function()
  {//关闭来自客户端的socket
    if(this.outputStream)
    {//关闭输出流
      this.outputStream.close(null);
      this.outputStream = null;
    }
    if(this.socket)
    {//关闭对应的socket
      this.socket.close(null);
      this.socket = null;
    }
  },

  broadcast: function(value)
  {//向客户端发送数据
    if(!this.outputStream)
    {
      this.closeSocket();
      return false;
    }
    try
    {
      this.outputStream.write(value, value.length);//发送数据
    }
    catch (e)
    {
      this.closeSocket();
      return false;
    }
    return true;
  }
}

const tBirdBiffServerSocketListener =
{
  onSocketAccepted: function(serverSocket, clientSocket)
  {//接受来自客户端的请求
    var connection = new tBirdBiffServerConnection();//新建一个连接对象
    //保存当前接收的连接
    if(connection.setSocket(clientSocket))
    {
      var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
      //向客户端发送数据
      if(connection.broadcast(server.getMailStatus()))
      {
        server.addConnection(connection);//保存连接对象到在线连接集合中
      }
      else
      {
        alert("connection NOT added");
      }
      server = null;
    }
    else
    {
      alert("Creating connection failed");
    }
    connection = null;
  },

  onStopListening: function(serverSocket, status)
  {//服务器停止监听
     alert("Server socket has stopped listening");
  }
}


服务器邮箱状态监听者,负责监视邮箱的状态变化:
const tBirdBiffServerBiffStateListener =
{
  timer: null,//定时器,负责定时检查邮箱状态
  clearIntervalTimeout: function()
  {//清除定时器
    if(this.timer)
    {
      this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer);
      this.timer.cancel();
      this.timer = null;
    }
    else
    {
      alert("Timer is null");
    }
  },

  OnItemIntPropertyChanged: function(item, property, oldValue, newValue)
  {//参见Thunderbird源代码,此函数负责监视各个文件夹的属性变化,当有新邮件到来时,property的值为“BiffState”
    if(property.toString() != "BiffState")
    {
      return;
    }
    this.clearIntervalTimeout();
    //启动一个定时器
    this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer);
    this.timer.initWithCallback(tBirdBiffServerCheckCallback, 1000, this.timer.TYPE_ONE_SHOT);
  }
}

实际的检查邮箱状态的处理过程放在tBirdBiffServerCheckCallback函数中。
const tBirdBiffServerCheckCallback =
{//定时检查邮箱状态的处理函数
  notify: function(timer)
  {
    var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
    server.check();//检查邮箱状态
    server = null;
  }
}


   Ok,本文用javascript,遵循XPCOM规范实现了一个简单的TCP服务器,服务器类型为阻塞式I/O,客户端代码将在下一篇文章中介绍。

 Reference:
1, https://addons.mozilla.org/en-US/thunderbird/addon/3788



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/05/19/1202823.html,如需转载请自行联系原作者