我正在使用libssh2创建一个用于执行SSH命令的C ++类。
libssh2 SSH会话的生命周期经历了以下几个阶段:
在第1步之前,我们必须打开一个套接字,我们在步骤2中传递给libssh2。从那时起,我们不再需要传递套接字,因为libssh2将存储对它的引用。在第4步之后,我们可以关闭套接字。
我通过类(SSHSession
)公开了这个,我希望 setup (步骤1和2)发生在ctor和 teardown (步骤3和4)在dtor上发生(因为第2步非常耗时,这将允许我保持一个会话池打开并重用它来执行命令)。
我的第一次尝试将所有代码都集中在SSHSession
上,并且它的ctor很快变得一团糟,“如果这一步失败了,那么我们必须看看已经完成的任务并将其撤消”。 dtor并不复杂,但我仍觉得它“太忙”了。
然后,我将工作划分为几个类,为每个获取/释放步骤实现RAII,即:
我创建了一个实现步骤2和3的类SessionConnection
,并且有一个类型为SessionHandle
的成员实现了步骤1和4;它还将套接字作为数据成员,在ctor / dtor上创建了第一个顺序依赖 - 在SessionHandle
成员之前无法销毁套接字。
当我考虑我的设计时,我想我可以像这样安排第2步和第3步:
2.1。握手(在远程主机上建立SSH会话)
2.2。认证
3.断开连接(终止远程主机上的SSH会话)
这意味着我可以进一步简化我的SessionConnection
类,实现另一个类来执行步骤2.1和3中的RAII,最后得到这样的结果:
SSHSession
有一个SessionConnection
数据成员。SessionConnection
实施第2.2步。SessionConnection
有一个套接字数据成员。SessionConnection
有一个SessionHandle
数据成员,它实现了步骤1和4.这必须在套接字之前销毁。SessionConnection
有一个RemoteSessionHandle
数据成员,它实现了步骤2.1和3.这必须在SessionHandle
数据成员之后创建并销毁。这极大地简化了我的ctors / dtors,由RAII提供。我发现概念上合理;如果,一方面,我们可以将这些视为SSH会话所处的状态,另一方面,我们也可以将它们视为我们正在管理的资源(本地,远程)。
但是,我现在在SessionConnection
有一个严格的建设/破坏命令,虽然我认为这是一个改进(我在研究中没有发现“这是邪恶的”,但只有“这应该是清楚的”记录“),我对其他意见感兴趣,我很乐意接受有关此设计可能替代方案的信息/指示。
到目前为止我看过的内容:
感谢您的时间。
答案 0 :(得分:1)
这种设计似乎没有任何根本性的错误。
如果您想取消对SessionConnection
成员的构造/销毁顺序的限制,您可以执行以下操作:
SSHSession
SSHConnection
成员SSHConnection
LocalSessionHandle
成员LocalSessionHandle
Socket
成员成员及其包含类的已定义构造/销毁顺序可确保按正确顺序执行步骤。