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