这个系列的前两篇文章主要是根据自己的需求,对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,如需转载请自行联系原作者