在上一篇《基于MozillaThunderBird的扩展开发(五)---进程间通信之Socket篇(上)》中开发了一个简单的TCP服务器,本文将介绍其对应的客户端。
在上一篇《基于Mozilla Thunderbird的扩展开发(五)---进程间通信之Socket篇(上)》中开发了一个简单的TCP服务器,本文将介绍其对应的客户端。
客户端代码:
const tBirdBiffClientUi =

{
tBirdBiffClientOnLoad: function()

{
// remove to avoid duplicate initialization
removeEventListener("load", tBirdBiffClientUi.tBirdBiffClientOnLoad, true);
//初始化客户端
var client = Components.classes["@phinecos.cnblogs.com/TBbiff/client;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
client.initialize();
var windowCount = client.getWindowCollection().Count();
client.addWindow(window);
client = null;
tBirdBiffClientObserver.updateUi();//更新UI
// register for notifications
var service = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
service.addObserver(tBirdBiffClientObserver, "thunderbirdBiff.uiUpdate", false);//加入监控者
service = null;
},

tBirdBiffClientOnClose: function()

{
// remove to avoid duplicate initialization
removeEventListener("close", tBirdBiffClientUi.tBirdBiffClientOnClose, true);
var service = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
service.removeObserver(tBirdBiffClientObserver, "thunderbirdBiff.uiUpdate");//移除监控者
service = null;

var client = Components.classes["@phinecos.cnblogs.com/TBbiff/client;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
client.removeWindow(window);//移除窗口
client = null;
}
}
addEventListener("load", tBirdBiffClientUi.tBirdBiffClientOnLoad, true);
addEventListener("close", tBirdBiffClientUi.tBirdBiffClientOnClose, true);

客户类:
const CI = Components.interfaces, CC = Components.classes, CR = Components.results;
tBirdBiffClient.classID = Components.ID("{5b0bccd0-83b9-11db-9fe1-0800200c9a66}");
tBirdBiffClient.contractID = "@phinecos.cnblogs.com/TBbiff/client;1";
tBirdBiffClient.classDescription = "Biff Client Service";

function tBirdBiffClient()


{
this.timer = CC["@mozilla.org/timer;1"].getService(CI.nsITimer);//定时器
this.interval = null;//定时器时间间隔
this.socketTransport = null;
this.biffState = null;//邮箱状态
this.socket = null;//socket对象
this.input = null;//输入流
this.port = null;//服务器端口
this.hostname = null;//服务器主机名称
this.windowCollection = CC["@mozilla.org/supports-array;1"].createInstance(CI.nsICollection);//客户端窗口集合
this.initialized = false;//是否已经初始化
}

tBirdBiffClient.prototype =


{
getConnection: function()

{
this.closeSocket();//关闭先前的连接
this.socket = this.socketTransport.createTransport(null, 0, this.hostname, this.port, null);//创建socket连接
if(!this.socket)

{
return;
}
var stream = this.socket.openInputStream(CI.nsITransport.OPEN_BLOCKING | CI.nsITransport.OPEN_UNBUFFERED, 0, 0);//打开输入流,类型为阻塞式,无缓冲
if(!stream)

{
this.closeSocket();
return;
}
this.input = CC["@mozilla.org/scriptableinputstream;1"].createInstance(CI.nsIScriptableInputStream);
if(!this.input)

{
this.closeSocket();
return;
}
this.input.init(stream);//初始化输入流
},
closeSocket: function()

{//关闭socket连接
if(this.input)

{
this.input.close(null);
this.input = null;
}

if(this.socket)

{
this.socket.close(null);
this.socket = null;
}
},
currentEventQueue: function()

{//当前事件队列
var EQS = CC["@mozilla.org/event-queue-service;1"].getService(CI.nsIEventQueueService);
return EQS.getSpecialEventQueue(EQS.CURRENT_THREAD_EVENT_QUEUE);
},
initialize: function()

{//初始化客户端
if(this.initialized)

{
return;
}

this.getIntervalPref();//获取时间间隔
this.hostname = this.utility.getHostnamePref();//获取主机名称
this.port = this.utility.getPortPref();//获取端口
this.socketTransport = CC["@mozilla.org/network/socket-transport-service;1"].getService(CI.nsISocketTransportService);
this.getConnection();//创建socket连接
this.timer.initWithCallback(tBirdBiffCheckMailCallback, 1000, this.timer.TYPE_ONE_SHOT);//启动定时器监听来自服务器的响应
this.initialized = true;
},
updateUi: function(result)

{//更新客户端UI
var state;
switch(result)

{
case "":

{
state = "offline";
break;
}
case "0":

{
state = "noMail";
break;
}
case "1":

{
state = "newMail";
break;
}
case "-1":

{
state = "error";
break;
}
default:

{
state = "weirdness";
break;
}
}
this.biffState = state;
state = null;
var service = CC["@mozilla.org/observer-service;1"].getService(CI.nsIObserverService);
service.notifyObservers(null, "thunderbirdBiff.uiUpdate", null);
service = null;
},
checkForMail: function()

{//检查是否有数据到来
this.timer.initWithCallback(tBirdBiffReadFromServerCallback, 1000, this.timer.TYPE_ONE_SHOT);
},

readFromServer: function()

{//从服务器读取数据
if(!this.input)

{//还未初始化输入流
this.getConnection();
}
try

{
var result = this.input.read(1);//读取数据
if(result.length == 1)

{
this.updateUi(result);//更新状态
}
result = null;
}
catch (e)

{
this.getConnection();
this.updateUi("");
}
this.timer.initWithCallback(tBirdBiffCheckMailCallback, this.interval, this.timer.TYPE_ONE_SHOT);//设置定时器
},
}

客户端监听者,负责监视邮箱的状态变化和读取来自服务器端的数据:
const tBirdBiffReadFromServerCallback =


{
notify: function(timer)

{//从服务器读取数据
var client = CC[tBirdBiffClient.contractID].getService(CI.nsISupports).wrappedJSObject;
client.readFromServer();
client = null;
}
}

const tBirdBiffCheckMailCallback =


{
notify: function(timer)

{//检查邮箱状态
var client = CC[tBirdBiffClient.contractID].getService(CI.nsISupports).wrappedJSObject;
client.checkForMail();
client = null;
}
}

为了测试服务器和客户端,我们使用firefox作为客户端的载体,thunderbird作为服务器端载体,可以看到thunderbird的邮箱状态会定时传给firefox,从而使得后者能随之更新其状态。
Reference:
1, https://addons.mozilla.org/en-US/thunderbird/addon/3788
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述