首页 »编程综合 » thunderbird:基于Mozilla Thunderbird的扩展开发( 5)---进程间通信的Socket篇(上) »正文
thunderbird:基于Mozilla Thunderbird的扩展开发( 5)---进程间通信的Socket篇(上)
来源: 发布时间:星期四, 2009年1月15日 浏览:29次 评论:0
这个系列 ![](/icons/51192de.gif) 前两篇文章主要是根据自己 ![](/icons/51192de.gif) 需求 ![](/icons/51192dou.gif) 对Thunderbird ![](/icons/51192de.gif) 源代码进行修改 ![](/icons/51192dou.gif) 改进了Thunderbird ![](/icons/51192de.gif) 现有功能 ![](/icons/51192dou.gif) 关注点都在Thunderbird ![](/icons/51192de.gif) 老本行---邮件客户端 ![](/icons/51192de.gif) 实现上 ![](/icons/51192dou.gif) 那是否Thunderbird就仅仅是 ![](/icons/51192yi.gif) 个邮件客户端呢?在我看来 ![](/icons/51192dou.gif) 并非如此 ![](/icons/51192dou.gif) 它源自Mozilla内核 ![](/icons/51192dou.gif) 就继承了Mozilla平台 ![](/icons/51192de.gif) 光荣传统 ![](/icons/51192dou.gif) 应该视为 ![](/icons/51192yi.gif) 个优秀 ![](/icons/51192de.gif) 可扩展 ![](/icons/51192de.gif) 开发平台 ![](/icons/51192dou.gif) 更进 ![](/icons/51192yi.gif) 步来看 ![](/icons/51192dou.gif) Mozilla ![](/icons/51192de.gif) 文化深入其骨髓 ![](/icons/51192dou.gif) 可以看到后来Adobe ![](/icons/51192de.gif) Flex,MicroSoft ![](/icons/51192de.gif) WPF都吸收了Mozilla平台界面和逻辑相分离 ![](/icons/51192de.gif) 思想,所以接下来几篇文章我想写 ![](/icons/51192yi.gif) 个比较有意思 ![](/icons/51192de.gif) 方面----进程间通信 ![](/icons/51192dou2.gif) 进程间通信 ![](/icons/51192de.gif) 概念在操作系统中有过详细 ![](/icons/51192de.gif) 介绍 ![](/icons/51192dou.gif) 思路方法很多 ![](/icons/51192dou.gif) 我主要关注其中两种: ![](/icons/51192socket.gif) 通信 ![](/icons/51192dou.gif) Pipe(管道)通信 ![](/icons/51192dou2.gif) 本文 ![](/icons/51192de.gif) 目 ![](/icons/51192de.gif) 就是开发 ![](/icons/51192yi.gif) 个扩展 ![](/icons/51192dou.gif) 展示TCP/IP ![](/icons/51192socket.gif) 技术在Mozilla扩展开发中 ![](/icons/51192de.gif) 应用 ![](/icons/51192dou2.gif) 服务器端主代码: const tBirdB fServerUi = { tBirdB fServerOnLoad: function![](/icons/51192kh.gif) {//启动服务器 // remove to avoid duplicate initialization removeEventListener("load", tBirdB fServerUi.tBirdB fServerOnLoad, true); tBirdB fCommon. IconPosition ;//设置图标位置 //创建服务器对象并 化 var server = Components. es["@phinecos.cnblogs.com/TBb f/server;1"].getService(Components. erfaces.nsISupports).wrappedJSObject; server.initialize ; server.addWindow(window);//保存当前窗口 server = null; }, tBirdB fServerOnClose: function![](/icons/51192kh.gif) {//关闭服务器 // remove to avoid duplicate initialization removeEventListener("close", tBirdB fServerUi.tBirdB fServerOnClose, true); //移除当前窗口 var server = Components. es["@dpwhite.com/thunderbirdb f/server;1"].getService(Components. erfaces.nsISupports).wrappedJSObject; server.removeWindow(window); server = null; } } addEventListener("load", tBirdB fServerUi.tBirdB fServerOnLoad, true); addEventListener("close", tBirdB fServerUi.tBirdB fServerOnClose, true);
服务器类 ![](/icons/51192dou.gif) 负责创建服务器端 ![](/icons/51192socket.gif) ,并异步监听来自客户端 ![](/icons/51192de.gif) 请求 ![](/icons/51192dou.gif) 管理邮箱状态 ![](/icons/51192de.gif) 变化和来自客户端 ![](/icons/51192de.gif) 连接 ![](/icons/51192dou2.gif) 服务器类 const CI = Components. erfaces, CC = Components. es, CR = Components.results; const Mail= "1"; const noMail = "0"; const serverError = "9"; tBirdB fServer. ID = Components.ID("{d2c9b4c6-2851-4d25-8cb6-3d3b037f8e1e}");//组件ID tBirdB fServer.contractID = "@phinecos.cnblogs.com/TBb f/server;1"; tBirdB fServer. Description = "TBb f Server Service"; function tBirdB fServer![](/icons/51192kh.gif) { this.utility = CC[utilityContractID].getService(CI.nsISupports).wrappedJSObject;//工具类对象 this.prefs = CC["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefBranch); this.connections = CC["@mozilla.org/supports- .gif' />;1"].createInstance(CI.nsICollection);//客户端连接集合 this.useAnimation = null;//是否使用动画效果 this.mailStatus = noMail;//邮箱状态 this.serverSocket = null;//服务器端![](/icons/51192socket.gif) this.port = null;//服务器端口 this.windowCollection = CC["@mozilla.org/supports- .gif' />;1"].createInstance(CI.nsICollection);//保存 窗口集合 this.initialized = false;//是否已经 化 } broadcast: function![](/icons/51192kh.gif) {//向客户端发送数据 var deadConnections = Array ;//已断开 连接 var status = this.mailStatus;//获取当前邮箱状态 var count = this.connections.Count ;//来自客户端 连接数目 //依次向各个客户端发送服务器 邮箱状态 for(var i = 0; i < count; i ) { var connection = this.connections.GetElementAt(i);//来自客户端 连接 connection = connection.wrappedJSObject; //发送数据给客户端 (!connection.broadcast(status)) { connection.closeSocket ;//关闭此断开 连接 deadConnections[i] = connection; } ![](/icons/51192else.gif) { deadConnections[i] = null; } connection = null; } for(var i = 0; i < deadConnections.length; i ) {//移除已经断开 连接 (deadConnections[i] != null) { this.removeConnection(deadConnections[i]); } } deadConnections = null; count = null; }, addConnection: function(value) {//加入新 来自客户端 连接 this.connections.AppendElement(value); }, removeConnection: function(value) {//移除连接 this.connections.RemoveElement(value); }, getServerSocket: function![](/icons/51192kh.gif) {//创建服务器端![](/icons/51192socket.gif) 并开始异步监听来自客户端 request this.serverSocket = CC["@mozilla.org/network/server- ;1"].createInstance(CI.nsIServerSocket); (!this.serverSocket) { alert("Unable to get a server "); } ![](/icons/51192else.gif) { try { this.serverSocket.init(this.port, false, -1);// 化服务器端 ,绑定到端口号port this.serverSocket.asyncListen(tBirdB fServerSocketListener);//开始异步监听来自客户端 请求 } catch(e) { this.serverSocket = null; } } }, closeServerSocket: function![](/icons/51192kh.gif) {//关闭服务器端![](/icons/51192socket.gif) (!this.serverSocket) { this.serverSocket.close(null); this.serverSocket = null; } }, initialize: function![](/icons/51192kh.gif) {// 化服务器 (this.initialized) {//已经 化过了 ; } this.port = 25501;//设置服务器监听端口 this.useAnimation = true; this.getServerSocket ;//创建服务器端 并开始监听 this.monitorB f(true);//监控状态变化 this.initialized = true; }, monitorB f: function(isStarting) {//监控邮箱状态变化 var sessionService = CC["@mozilla.org/messenger/services/session;1"].getService(CI.nsIMsgMailSession); (isStarting) { sessionService.AddFolderListener(tBirdB fServerB fStateListener, CI.nsIFolderListener. PropertyChanged);//增加监听者 } ![](/icons/51192else.gif) { sessionService.RemoveFolderListener(tBirdB fServerB fStateListener, CI.nsIFolderListener. PropertyChanged);//移除监听者 } sessionService = null; }, closeAllConnections: function![](/icons/51192kh.gif) {//关闭所有来自客户端 连接 var count = this.connections.Count ; for(var i = 0; i < count; i ) { var connection = this.connections.GetElementAt(i); connection = connection.wrappedJSObject; connection.closeSocket ; connection = null; } count = null; this.connections.Clear ; }, finalize: function![](/icons/51192kh.gif) {//析构![](/icons/51192hanshu.gif) (!this.initialized) { ; } this.closeServerSocket ;//关闭服务器端![](/icons/51192socket.gif) this.monitorB f(false);//移除监听邮箱状态 监听者 this.closeAllConnections ;//关闭所有来自客户端 连接 }, updateUi: function(window) {//刷新界面状态 var state; var tip = "T-Bird B f: "; var status = window.document.getElementById("thunderbird-b f"); switch(this.mailStatus) { noMail: {//没有新邮件 tip this.getLocalizedString("noNewMail"); state = "noMail"; ; } Mail: {//有新邮件 tip this.getLocalizedString(" Mail"); (this.useAnimation) { state = " MailAni"; // using g here due to animation } ![](/icons/51192else.gif) { state = " Mail"; } ; } default: {//error this.utility.logError("Unexpected result: " + this.mailStatus); tip = this.getLocalizedString("weirdness"); state = "weirdness"; ; } } status. Attribute("tooltiptext", tip); status. Attribute("b fState", state); tip = null; state = null; status = null; }, MailStatus: function(value) {//设置邮箱状态 (this.MailStatus value) {//没有变化 ; } this.mailStatus = value; //邮箱状态发生改变 逐个窗口通知其更新状态,这些窗口都是服务器端 Observer var server = CC[tBirdB fServer.contractID].getService(CI.nsISupports).wrappedJSObject; var windowCollection = server.getWindowCollection ; var count = windowCollection.Count ; for(var i = 0; i < count; i ) { var window = windowCollection.GetElementAt(i); this.updateUi(window);//更新此窗口状态 window = null; } this.broadcast ;//将服务器 邮箱状态通知给各个客户端 windowCollection = null; count = null; server = null; }, check: function![](/icons/51192kh.gif) {//检查服务器邮箱状态 tBirdB fServerB fStateListener.clearIntervalTimeout ;//清除此前 定时器 this. MailStatus(this.checkServers );//实际 检查动作 }, checkServers: function![](/icons/51192kh.gif) { try { const b fShowsMailReady = 0; //帐户管理器 var accountManager = CC["@mozilla.org/messenger/account-manager;1"].getService(CI.nsIMsgAccountManager); (accountManager) { //获取此用户 所有服务器 var servers = accountManager.allServers; var numServers = servers.Count ; for(var i = 0; i < numServers; i ) { var server = servers.GetElementAt(i).QueryInterface(CI.nsIMsgIncomingServer); (server.rootFolder != server.rootMsgFolder) { continue; } (server.type != "pop3" && server.type != "imap") { (server accountManager.localFoldersServer) { alert("tBirdB fServer.checkServers"+server.prettyName + " appears to be Local Folders"); } ![](/icons/51192else.gif) { alert("Non-pop3, IMAP, or Local Folders server found. Type is " + server.type + ", name is " + server.prettyName); continue; } } (server.b fState b fShowsMailReady) {//有新邮件到来 server = null; servers = null; numServers = null; accountManager = null; Mail; } } //没有新邮件 servers = null; numServers = null; accountManager = null; noMail; } ![](/icons/51192else.gif) { accountManager = null; this.utility.logError("Unable to get account manager"); serverError; } } catch (e) { accountManager = null; serverError; } },
来自客户端 ![](/icons/51192de.gif) 连接对象类: function tBirdB fServerConnection![](/icons/51192kh.gif) { this.wrappedJSObject = this; } tBirdB fServerConnection.prototype = { : null,//客户端对应![](/icons/51192de.gif) ![](/icons/51192socket.gif) outputStream: null,//输出流 Socket: function(value) {//保存来自客户端![](/icons/51192de.gif) 连接 try { this.outputStream = value.openOutputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 0, 0);//打开输出流 类型为阻塞型 无缓冲区 } catch(e) { false; } (!this.outputStream) { false; } this. = value; true; }, closeSocket: function![](/icons/51192kh.gif) {//关闭来自客户端![](/icons/51192de.gif) ![](/icons/51192socket.gif) (this.outputStream) {//关闭输出流 this.outputStream.close(null); this.outputStream = null; } (this. ) {//关闭对应![](/icons/51192de.gif) ![](/icons/51192socket.gif) this. .close(null); this. = null; } }, broadcast: function(value) {//向客户端发送数据 (!this.outputStream) { this.closeSocket ; false; } try { this.outputStream.write(value, value.length);//发送数据 } catch (e) { this.closeSocket ; false; } true; } }
服务器监听类 ![](/icons/51192dou.gif) 负责监听来自客户端 ![](/icons/51192de.gif) 各个请求: function tBirdB fServerConnection![](/icons/51192kh.gif) { this.wrappedJSObject = this; } tBirdB fServerConnection.prototype = { : null,//客户端对应![](/icons/51192de.gif) ![](/icons/51192socket.gif) outputStream: null,//输出流 Socket: function(value) {//保存来自客户端![](/icons/51192de.gif) 连接 try { this.outputStream = value.openOutputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 0, 0);//打开输出流 类型为阻塞型 无缓冲区 } catch(e) { false; } (!this.outputStream) { false; } this. = value; true; }, closeSocket: function![](/icons/51192kh.gif) {//关闭来自客户端![](/icons/51192de.gif) ![](/icons/51192socket.gif) (this.outputStream) {//关闭输出流 this.outputStream.close(null); this.outputStream = null; } (this. ) {//关闭对应![](/icons/51192de.gif) ![](/icons/51192socket.gif) this. .close(null); this. = null; } }, broadcast: function(value) {//向客户端发送数据 (!this.outputStream) { this.closeSocket ; false; } try { this.outputStream.write(value, value.length);//发送数据 } catch (e) { this.closeSocket ; false; } true; } } const tBirdB fServerSocketListener = { onSocketAccepted: function(serverSocket, clientSocket) {//接受来自客户端 请求 var connection = tBirdB fServerConnection ;//新建 个连接对象 //保存当前接收 连接 (connection. Socket(clientSocket)) { var server = CC[tBirdB fServer.contractID].getService(CI.nsISupports).wrappedJSObject; //向客户端发送数据 (connection.broadcast(server.getMailStatus )) { server.addConnection(connection);//保存连接对象到在线连接集合中 } ![](/icons/51192else.gif) { alert("connection NOT added"); } server = null; } ![](/icons/51192else.gif) { alert("Creating connection failed"); } connection = null; }, onStopListening: function(serverSocket, status) {//服务器停止监听 alert("Server has stopped listening"); } }
服务器邮箱状态监听者 ![](/icons/51192dou.gif) 负责监视邮箱 ![](/icons/51192de.gif) 状态变化: const tBirdB fServerB fStateListener = { timer: null,//定时器 负责定时检查邮箱状态 clearIntervalTimeout: function![](/icons/51192kh.gif) {//清除定时器 (this.timer) { this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer); this.timer.cancel ; this.timer = null; } ![](/icons/51192else.gif) { alert("Timer is null"); } }, OnItemIntPropertyChanged: function(item, property, oldValue, Value) {//参见Thunderbird源代码 此 负责监视各个文件夹 属性变化,当有新邮件到来时 property 值为“B fState” (property.toString != "B fState") { ; } this.clearIntervalTimeout ; //启动 个定时器 this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer); this.timer.initWithCallback(tBirdB fServerCheckCallback, 1000, this.timer.TYPE_ONE_SHOT); } } 实际 ![](/icons/51192de.gif) 检查邮箱状态 ![](/icons/51192de.gif) 处理过程放在tBirdB ![](/icons/51192if.gif) fServerCheckCallback ![](/icons/51192hanshu.gif) 中 ![](/icons/51192dou2.gif) const tBirdB fServerCheckCallback = {//定时检查邮箱状态 处理![](/icons/51192hanshu.gif) not y: function(timer) { var server = CC[tBirdB fServer.contractID].getService(CI.nsISupports).wrappedJSObject; server.check ;//检查邮箱状态 server = null; } } Ok,本文用javascript ![](/icons/51192dou.gif) 遵循XPCOM规范标准实现了 ![](/icons/51192yi.gif) 个简单 ![](/icons/51192de.gif) TCP服务器 ![](/icons/51192dou.gif) 服务器类型为阻塞式I/O ![](/icons/51192dou.gif) 客户端代码将在下 ![](/icons/51192yi.gif) 篇文章中介绍
相关文章
读者评论
发表评论
|
|