这是一个通用的问题。我不是在寻找最好的答案,我希望你能表达你最喜欢的做法。
我想用Java实现一个网络协议(但这是一个相当普遍的问题,我在C ++中面临同样的问题),这不是第一次,正如我之前所做的那样。但我认为我错过了实施它的好方法。实际上通常都是关于在主机之间交换文本消息和一些字节缓冲区,存储状态并等到下一条消息到来。问题是我通常最终得到一堆开关,并且或多或少复杂的if语句对不同的状态/消息作出反应。整件事情通常变得复杂而难以保持。更不用说有时出现的东西有一些“盲点”,我的意思是协议的状态没有被覆盖并且以不可预测的方式表现。我试着写下一些状态机类,负责以或多或少的智能方式检查每个动作的开始和结束状态。这使编程协议变得非常复杂,因为我必须编写行和代码行来覆盖每种可能的情况。 我喜欢的是一个好的模式,或者用于编写复杂协议的最佳实践,易于维护和扩展,并且非常易读。
你有什么建议?
答案 0 :(得分:16)
阅读 State 设计模式,了解如何避免大量的switch语句。
“有时会出现一些”盲点“,我的意思是协议的状态尚未涵盖......”
州可以帮助避免差距。它不能保证良好的设计,你仍然必须这样做。
“......因为我必须编写代码行和代码行以涵盖所有可能的情况。”
这不应被视为负担或问题:您必须编写代码行以涵盖所有可能的情况。
状态可以提供帮助,因为您可以利用继承。它不能保证良好的设计,你仍然必须这样做。
答案 1 :(得分:6)
设计协议通常都与您正在使用的应用程序空间有关。例如,http就是处理网页,图形和帖子,而FTP则是关于传输文件。
简而言之,首先,您应该确定您所在的应用程序空间,然后定义需要采取的操作。最后,在你开始设计你的实际协议之前,你应该认真地,认真地寻找另一个做你想做的事情的协议栈,并避免实现协议栈altoether。只有在您确定预先构建的其他内容绝对不适合您之后,才能开始构建自己的协议栈。
答案 2 :(得分:3)
有限状态机就是你想要的
所以你定义了一大堆你可以作为接收者或发送者的状态(idle,connecting_phase1,connecting_phase2,packet expected,......)
然后定义所有可能的事件(packet1到达,net关闭,......)
最后你有一个表,说'当状态为x且事件n发生了func y并转换到状态q'时 - 表示每个状态和事件(很多都是空或重复)
编辑 - 如何制作FSM(草图)
struct FSMNode
{
int m_nextState;
void (m_func*);
}
FSMNode states[NUMSTATES][NUMEVENTS]=
{ // state 0
{3, bang}, // event 0
{2,wiz},
{1, fertang}
}
{
{1, noop}, // event 0
{1, noop},
{3, ole}
}
.......
FSMNode node = states[mystate][event];
node.m_func(context);
mystate = node.m_nextState;
我确信这充满了无效的语法 - 但我希望你得到漂移
答案 3 :(得分:3)
在C ++中,您可以使用Boost :: Spirit库轻松解析协议消息。唯一的“难点”是定义消息协议的语法。看看Gnutella源代码,看看他们是如何解决这个问题的。这里http://www9.limewire.com/developer/gnutella_protocol_0.4.pdf是Gnutella协议规范
答案 4 :(得分:2)
为什么不使用XML作为协议?您可以在XML节点内封装和分类所有数据
答案 5 :(得分:2)
不能自己给你一个例子,但是如何看待其他(有能力的)人们如何做呢?
喜欢这个吗? http://anonsvn.jboss.org/repos/netty/trunk/src/main/java/org/jboss/netty/handler/codec/http/
P.S。就此而言,我实际上建议使用netty作为您的网络框架,并在其上构建您的协议。它应该很容易,你可能会摆脱一堆头痛......
答案 6 :(得分:1)
如果您使用的是Java,请考虑查看Apache MINA,它的文档和示例应该以正确的方式激励您。
答案 7 :(得分:0)
右键单击系统任务栏中的网络连接图标。 单击疑难解答。 故障排除者可能会发现并解决问题,在这种情况下,您可以快速开始业务。 如果疑难解答无法解决Winsocks问题,则可能会出现类似以下的错误: “此计算机上缺少一个或多个网络协议”