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

本文介绍如何基于Mozilla Thunderbird开发扩展,实现服务器端的TCP/IP Socket通信。通过JavaScript和XPCOM规范,创建了一个简单的阻塞式I/O TCP服务器,用于监控邮箱状态变化,并通过Socket向客户端发送状态更新。

      <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

20080506.bmp

Mozilla扩展系列链接:

1浅谈基于Mozilla Thunderbird的扩展开发

2基于Mozilla平台的扩展开发(续)----XPCOM组件篇

3基于Mozilla Thunderbird的扩展开发(三)---如何获取邮件的完整信息

4基于Mozilla Thunderbird的扩展开发(四)---修改源代码实现自动保存附件

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

      这个系列的前两篇文章主要是根据自己的需求,对Thunderbird的源代码进行修改,改进了Thunderbird的现有功能,关注点都在Thunderbird的老本行---邮件客户端的实现上,那是否Thunderbird就仅仅是一个邮件客户端呢?在我看来,并非如此,它源自Mozilla内核,就继承了Mozilla平台的光荣传统,应该视为一个优秀的可扩展的开发平台,更进一步来看,Mozilla的文化深入其骨髓,可以看到后来AdobeFlex,MicroSoftWPF都吸收了Mozilla平台界面与逻辑相分离的思想,所以接下来几篇文章我想写一个比较有意思的方面----进程间通信。

      进程间通信的概念在操作系统中有过详细的介绍,方法很多,我主要关注其中两种:socket通信,Pipe(管道)通信。

      本文的目的就是开发一个扩展,展示TCP/IP socket技术在Mozilla扩展开发中的应用。

服务器端主代码:

None.gif   const tBirdBiffServerUi  =
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif {
InBlock.gif    tBirdBiffServerOnLoad: 
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//启动服务器
InBlock.gif
      // remove to avoid duplicate initialization
InBlock.gif
      removeEventListener("load", tBirdBiffServerUi.tBirdBiffServerOnLoad, true);
InBlock.gif      tBirdBiffCommon.setIconPosition();
//设置图标位置
InBlock.gif
    //创建服务器对象并初始化
InBlock.gif
      var server = Components.classes["@phinecos.cnblogs.com/TBbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
InBlock.gif      server.initialize();
InBlock.gif      server.addWindow(window);
//保存当前窗口
InBlock.gif
      server = null;
ExpandedSubBlockEnd.gif    }
,
InBlock.gif    tBirdBiffServerOnClose: 
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//关闭服务器
InBlock.gif
      // remove to avoid duplicate initialization
InBlock.gif
      removeEventListener("close", tBirdBiffServerUi.tBirdBiffServerOnClose, true);
InBlock.gif
InBlock.gif    
//移除当前窗口
InBlock.gif
      var server = Components.classes["@dpwhite.com/thunderbirdbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
InBlock.gif      server.removeWindow(window);
InBlock.gif      server 
= null;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif  }

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


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

ContractedBlock.gif ExpandedBlockStart.gif 服务器类
None.gifconst CI = Components.interfaces, CC = Components.classes, CR = Components.results;
None.gifconst newMail
= "1";
None.gifconst noMail 
= "0";
None.gifconst serverError 
= "9";
None.gif
None.giftBirdBiffServer.classID 
= Components.ID("{d2c9b4c6-2851-4d25-8cb6-3d3b037f8e1e}");//组件ID
None.gif
tBirdBiffServer.contractID = "@phinecos.cnblogs.com/TBbiff/server;1";
None.giftBirdBiffServer.classDescription 
= "TBbiff Server Service";
None.gif
None.gif
function tBirdBiffServer()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
this.utility = CC[utilityContractID].getService(CI.nsISupports).wrappedJSObject;//工具类对象
InBlock.gif
  this.prefs = CC["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefBranch);
InBlock.gif  
this.connections = CC["@mozilla.org/supports-array;1"].createInstance(CI.nsICollection);//客户端连接集合
InBlock.gif
  this.useAnimation = null;//是否使用动画效果
InBlock.gif
  this.mailStatus = noMail;//邮箱状态
InBlock.gif
  this.serverSocket = null;//服务器端socket
InBlock.gif
  this.port = null;//服务器端口
InBlock.gif
  this.windowCollection = CC["@mozilla.org/supports-array;1"].createInstance(CI.nsICollection);//保存的窗口集合
InBlock.gif
  this.initialized = false;//是否已经初始化
ExpandedBlockEnd.gif
}

None.gif
None.gif  broadcast: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//向客户端发送数据
InBlock.gif
    var deadConnections = new Array();//已断开的连接
InBlock.gif
    var status = this.mailStatus;//获取当前邮箱状态
InBlock.gif
    var count = this.connections.Count();//来自客户端的连接数目
InBlock.gif

InBlock.gif    
//依次向各个客户端发送服务器的邮箱状态
InBlock.gif
    for(var i = 0; i < count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
var connection = this.connections.GetElementAt(i);//来自客户端的连接
InBlock.gif
      connection = connection.wrappedJSObject;
InBlock.gif    
InBlock.gif      
//发送数据给客户端
InBlock.gif
      if(!connection.broadcast(status))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        connection.closeSocket();
//关闭此断开的连接
InBlock.gif
        deadConnections[i] = connection;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
else
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        deadConnections[i] 
= null;
ExpandedSubBlockEnd.gif      }

InBlock.gif
InBlock.gif      connection 
= null;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
for(var i = 0; i < deadConnections.length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//移除已经断开的连接
InBlock.gif
      if(deadConnections[i] != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
this.removeConnection(deadConnections[i]);
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    deadConnections 
= null;
InBlock.gif    count 
= null;
ExpandedBlockEnd.gif  }
,
None.gif
None.gif  addConnection: 
function(value)
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//加入新的来自客户端的连接
InBlock.gif
    this.connections.AppendElement(value);
ExpandedBlockEnd.gif   }
,
None.gif
None.gif  removeConnection: 
function(value)
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//移除连接
InBlock.gif
    this.connections.RemoveElement(value);
ExpandedBlockEnd.gif  }
,
None.gif  getServerSocket: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//创建服务器端socket,并开始异步监听来自客户端的request
InBlock.gif
    this.serverSocket = CC["@mozilla.org/network/server-socket;1"].createInstance(CI.nsIServerSocket);
InBlock.gif    
if(!this.serverSocket)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      alert(
"Unable to get a server socket");
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
try
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
this.serverSocket.init(this.port, false-1);//初始化服务器端socket,绑定到端口号port
InBlock.gif
        this.serverSocket.asyncListen(tBirdBiffServerSocketListener);//开始异步监听来自客户端的请求
ExpandedSubBlockEnd.gif
      }

InBlock.gif      
catch(e)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif         
this.serverSocket = null;
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif  }
,
None.gif  closeServerSocket: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//关闭服务器端socket
InBlock.gif
    if(!this.serverSocket)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.serverSocket.close(null);
InBlock.gif      
this.serverSocket = null;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif  }
,
None.gif  initialize: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//初始化服务器
InBlock.gif
    if(this.initialized)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//已经初始化过了
InBlock.gif
      return;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
this.port = 25501;//设置服务器监听端口
InBlock.gif
    this.useAnimation = true;
InBlock.gif    
this.getServerSocket();//创建服务器端socket并开始监听
InBlock.gif
    this.monitorBiff(true);//监控状态变化
InBlock.gif
    this.initialized = true;
ExpandedBlockEnd.gif   }
,
None.gif  monitorBiff: 
function(isStarting)
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//监控邮箱状态变化
InBlock.gif
    var sessionService = CC["@mozilla.org/messenger/services/session;1"].getService(CI.nsIMsgMailSession);
InBlock.gif    
if(isStarting)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      sessionService.AddFolderListener(tBirdBiffServerBiffStateListener, CI.nsIFolderListener.intPropertyChanged);
//增加监听者
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      sessionService.RemoveFolderListener(tBirdBiffServerBiffStateListener, CI.nsIFolderListener.intPropertyChanged);
//移除监听者
ExpandedSubBlockEnd.gif
    }

InBlock.gif
InBlock.gif    sessionService 
= null;
ExpandedBlockEnd.gif  }
,
None.gif
None.gif  closeAllConnections: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//关闭所有来自客户端的连接
InBlock.gif
    var count = this.connections.Count();
InBlock.gif    
for(var i = 0; i < count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
var connection = this.connections.GetElementAt(i);
InBlock.gif      connection 
= connection.wrappedJSObject;
InBlock.gif      connection.closeSocket();
InBlock.gif      connection 
= null;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    count 
= null;
InBlock.gif    
this.connections.Clear();
ExpandedBlockEnd.gif  }
,
None.gif   finalize: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//析构函数
InBlock.gif
    if(!this.initialized)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
this.closeServerSocket();//关闭服务器端socket
InBlock.gif
    this.monitorBiff(false);//移除监听邮箱状态的监听者
InBlock.gif
    this.closeAllConnections();//关闭所有来自客户端的连接
ExpandedBlockEnd.gif
  }
,
None.gif
None.gif      updateUi: 
function(window)
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//刷新界面状态
InBlock.gif
    var state;
InBlock.gif    
var tip = "T-Bird Biff: ";
InBlock.gif    
var status = window.document.getElementById("thunderbird-biff");
InBlock.gif
InBlock.gif    
switch(this.mailStatus)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
case noMail:
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{//没有新邮件
InBlock.gif
        tip += this.getLocalizedString("noNewMail");
InBlock.gif        state 
= "noMail";
InBlock.gif        
break;
ExpandedSubBlockEnd.gif      }

InBlock.gif
InBlock.gif      
case newMail:
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{//有新邮件
InBlock.gif
        tip += this.getLocalizedString("newMail");
InBlock.gif        
if(this.useAnimation)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          state 
= "newMailAni"// using gif here due to animation
ExpandedSubBlockEnd.gif
        }

InBlock.gif        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          state 
= "newMail";
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
break;
ExpandedSubBlockEnd.gif      }

InBlock.gif
InBlock.gif      
default:
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{//error
InBlock.gif
        this.utility.logError("Unexpected result: " + this.mailStatus);
InBlock.gif        tip 
= this.getLocalizedString("weirdness");
InBlock.gif        state 
= "weirdness";
InBlock.gif        
break;
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    status.setAttribute(
"tooltiptext",  tip);
InBlock.gif    status.setAttribute(
"biffState",  state);
InBlock.gif    tip 
= null;
InBlock.gif    state 
= null;
InBlock.gif    status 
= null;
ExpandedBlockEnd.gif  }
,
None.gif
None.gif  setMailStatus: 
function(value)
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//设置邮箱状态
InBlock.gif
    if(this.MailStatus == value)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//没有变化
InBlock.gif
      return;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
this.mailStatus = value;
InBlock.gif    
//邮箱状态发生改变,逐个窗口通知其更新状态,这些窗口都是服务器端的Observer
InBlock.gif
    var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
InBlock.gif    
var windowCollection = server.getWindowCollection();
InBlock.gif    
var count = windowCollection.Count();
InBlock.gif    
for(var i = 0; i < count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
var window = windowCollection.GetElementAt(i);
InBlock.gif      
this.updateUi(window);//更新此窗口状态
InBlock.gif
      window = null;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
this.broadcast();//将服务器的邮箱状态通知给各个客户端
InBlock.gif

InBlock.gif    windowCollection 
= null;
InBlock.gif    count 
= null;
InBlock.gif    server 
= null;
ExpandedBlockEnd.gif  }
,
None.gif
None.gifcheck: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{//检查服务器邮箱状态
InBlock.gif
    tBirdBiffServerBiffStateListener.clearIntervalTimeout();//清除此前的定时器
InBlock.gif
    this.setMailStatus(this.checkServers());//实际的检查动作
ExpandedBlockEnd.gif
  }
,
None.gif
None.gif  checkServers: 
function()
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{
InBlock.gif    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      const biffShowsMailReady 
= 0;
InBlock.gif      
//帐户管理器
InBlock.gif
      var accountManager = CC["@mozilla.org/messenger/account-manager;1"].getService(CI.nsIMsgAccountManager);
InBlock.gif      
if(accountManager)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif          
//获取此用户的所有服务器
InBlock.gif
        var servers = accountManager.allServers;
InBlock.gif        
var numServers = servers.Count();
InBlock.gif
InBlock.gif        
for(var i = 0; i < numServers; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          
var server = servers.GetElementAt(i).QueryInterface(CI.nsIMsgIncomingServer);
InBlock.gif    
InBlock.gif          
if(server.rootFolder != server.rootMsgFolder)
ExpandedSubBlockStart.gifContractedSubBlock.gif          
dot.gif{
InBlock.gif            
continue;
ExpandedSubBlockEnd.gif          }

InBlock.gif
InBlock.gif          
if(server.type != "pop3" && server.type != "imap")
ExpandedSubBlockStart.gifContractedSubBlock.gif          
dot.gif{
InBlock.gif            
if(server == accountManager.localFoldersServer)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif             alert(
"tBirdBiffServer.checkServers"+server.prettyName + " appears to be Local Folders");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif              alert(
"Non-pop3, IMAP, or Local Folders server found. Type is " + server.type + ", name is " + server.prettyName);
InBlock.gif              
continue;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif          }

InBlock.gif          
if(server.biffState == biffShowsMailReady)
ExpandedSubBlockStart.gifContractedSubBlock.gif          
dot.gif{//有新邮件到来
InBlock.gif
            server = null;
InBlock.gif            servers 
= null;
InBlock.gif            numServers 
= null;
InBlock.gif            accountManager 
= null;
InBlock.gif            
return newMail;
ExpandedSubBlockEnd.gif          }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
//没有新邮件
InBlock.gif
        servers = null;
InBlock.gif        numServers 
= null;
InBlock.gif        accountManager 
= null;
InBlock.gif        
return noMail;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
else
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        accountManager 
= null;
InBlock.gif        
this.utility.logError("Unable to get account manager");
InBlock.gif        
return serverError;
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
catch (e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      accountManager 
= null;
InBlock.gif      
return serverError;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif  }
,
None.gif
None.gif来自客户端的连接对象类:
None.gif
function tBirdBiffServerConnection()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
this.wrappedJSObject = this;
ExpandedBlockEnd.gif}

None.gif
None.giftBirdBiffServerConnection.prototype 
=
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  socket: 
null,//客户端对应的socket
InBlock.gif
  outputStream: null,//输出流
InBlock.gif

InBlock.gif  setSocket: 
function(value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//保存来自客户端的socket连接
InBlock.gif
    try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.outputStream = value.openOutputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 00);//打开输出流,类型为阻塞型,无缓冲区
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
catch(e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif       
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if(!this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
this.socket = value;
InBlock.gif    
return true;
ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  closeSocket: 
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//关闭来自客户端的socket
InBlock.gif
    if(this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//关闭输出流
InBlock.gif
      this.outputStream.close(null);
InBlock.gif      
this.outputStream = null;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if(this.socket)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//关闭对应的socket
InBlock.gif
      this.socket.close(null);
InBlock.gif      
this.socket = null;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  broadcast: 
function(value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//向客户端发送数据
InBlock.gif
    if(!this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.closeSocket();
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.outputStream.write(value, value.length);//发送数据
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
catch (e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.closeSocket();
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
return true;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif


服务器监听类,负责监听来自客户端的各个请求:

None.gif function  tBirdBiffServerConnection()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
this.wrappedJSObject = this;
ExpandedBlockEnd.gif}

None.gif
None.giftBirdBiffServerConnection.prototype 
=
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  socket: 
null,//客户端对应的socket
InBlock.gif
  outputStream: null,//输出流
InBlock.gif

InBlock.gif  setSocket: 
function(value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//保存来自客户端的socket连接
InBlock.gif
    try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.outputStream = value.openOutputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 00);//打开输出流,类型为阻塞型,无缓冲区
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
catch(e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif       
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if(!this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
this.socket = value;
InBlock.gif    
return true;
ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  closeSocket: 
function()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//关闭来自客户端的socket
InBlock.gif
    if(this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//关闭输出流
InBlock.gif
      this.outputStream.close(null);
InBlock.gif      
this.outputStream = null;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
if(this.socket)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{//关闭对应的socket
InBlock.gif
      this.socket.close(null);
InBlock.gif      
this.socket = null;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  broadcast: 
function(value)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//向客户端发送数据
InBlock.gif
    if(!this.outputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.closeSocket();
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.outputStream.write(value, value.length);//发送数据
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
catch (e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.closeSocket();
InBlock.gif      
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
return true;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gifconst tBirdBiffServerSocketListener 
=
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  onSocketAccepted: 
function(serverSocket, clientSocket)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//接受来自客户端的请求
InBlock.gif
    var connection = new tBirdBiffServerConnection();//新建一个连接对象
InBlock.gif
    //保存当前接收的连接
InBlock.gif
    if(connection.setSocket(clientSocket))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
InBlock.gif      
//向客户端发送数据
InBlock.gif
      if(connection.broadcast(server.getMailStatus()))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        server.addConnection(connection);
//保存连接对象到在线连接集合中
ExpandedSubBlockEnd.gif
      }

InBlock.gif      
else
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        alert(
"connection NOT added");
ExpandedSubBlockEnd.gif      }

InBlock.gif      server 
= null;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      alert(
"Creating connection failed");
ExpandedSubBlockEnd.gif    }

InBlock.gif    connection 
= null;
ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  onStopListening: 
function(serverSocket, status)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//服务器停止监听
InBlock.gif
     alert("Server socket has stopped listening");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif


服务器邮箱状态监听者,负责监视邮箱的状态变化:

None.gif const tBirdBiffServerBiffStateListener  =
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  timer: 
null,//定时器,负责定时检查邮箱状态
InBlock.gif
  clearIntervalTimeout: function()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//清除定时器
InBlock.gif
    if(this.timer)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer);
InBlock.gif      
this.timer.cancel();
InBlock.gif      
this.timer = null;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      alert(
"Timer is null");
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }
,
InBlock.gif
InBlock.gif  OnItemIntPropertyChanged: 
function(item, property, oldValue, newValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{//参见Thunderbird源代码,此函数负责监视各个文件夹的属性变化,当有新邮件到来时,property的值为“BiffState”
InBlock.gif
    if(property.toString() != "BiffState")
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
this.clearIntervalTimeout();
InBlock.gif    
//启动一个定时器
InBlock.gif
    this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer);
InBlock.gif    
this.timer.initWithCallback(tBirdBiffServerCheckCallback, 1000this.timer.TYPE_ONE_SHOT);
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif

实际的检查邮箱状态的处理过程放在tBirdBiffServerCheckCallback函数中。

None.gifconst tBirdBiffServerCheckCallback  =
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {//定时检查邮箱状态的处理函数
InBlock.gif
  notify: function(timer)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
InBlock.gif    server.check();
//检查邮箱状态
InBlock.gif
    server = null;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif


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

 Reference:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值