java 如何实现网络协议?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2450408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:13:09  来源:igfitidea点击:

How to implement a network protocol?

javac++protocols

提问by gotch4

Here is a generic question. I'm not in search of the best answer, I'd just like you to express your favourite practices.

这是一个通用的问题。我不是在寻找最佳答案,我只是希望您表达您最喜欢的做法。

I want to implement a network protocol in Java (but this is a rather general question, I faced the same issues in C++), this is not the first time, as I have done this before. But I think I am missing a good way to implement it. In fact usually it's all about exchanging text messages and some byte buffers between hosts, storing the status and wait until the next message comes. The problem is that I usually end up with a bunch of switch and more or less complex if statements that react to different statuses / messages. The whole thing usually gets complicated and hard to mantain. Not to mention that sometimes what comes out has some "blind spot", I mean statuses of the protocol that have not been covered and that behave in a unpredictable way. I tried to write down some state machine classes, that take care of checking start and end statuses for each action in more or less smart ways. This makes programming the protocol very complicated as I have to write lines and lines of code to cover every possible situation. What I'd like is something like a good pattern, or a best practice that is used in programming complex protocols, easy to mantain and to extend and very readable.

我想用 Java 实现一个网络协议(但这是一个相当普遍的问题,我在 C++ 中遇到了同样的问题),这不是第一次,因为我以前做过。但我认为我缺少一个实现它的好方法。事实上,通常都是在主机之间交换文本消息和一些字节缓冲区,存储状态并等待下一条消息到来。问题是我通常会得到一堆 switch 和或多或少复杂的 if 语句,这些语句对不同的状态/消息做出反应。整个事情通常会变得复杂且难以维护。更不用说有时出现的内容有一些“盲点”,我的意思是协议的状态未被涵盖并且以不可预测的方式运行。我试着写下一些状态机类,负责以或多或少聪明的方式检查每个动作的开始和结束状态。这使得协议编程变得非常复杂,因为我必须编写一行又一行的代码来涵盖所有可能的情况。我想要的是一种很好的模式,或者是用于编程复杂协议的最佳实践,易于维护和扩展并且非常易读。

What are your suggestions?

你有什么建议?

采纳答案by S.Lott

Read up on the Statedesign pattern to learn how to avoid lots of switch statements.

阅读状态设计模式以了解如何避免大量 switch 语句。



"sometimes what comes out has some "blind spot", I mean statuses of the protocol that have not been covered..."

“有时出来的东西会有一些‘盲点’,我的意思是协议的状态没有被涵盖……”

Statecan help avoid gaps. It can't guarantee a good design, you still have to do that.

状态可以帮助避免差距。它不能保证一个好的设计,你仍然必须这样做。

"...as I have to write lines and lines of code to cover every possible situation."

“......因为我必须编写一行又一行的代码来涵盖所有可能的情况。”

This should not be considered a burden or a problem: You mustwrite lines of code to cover every possible situation.

这不应被视为负担或问题:您必须编写代码行以涵盖所有可能的情况。

Statecan help because you get to leverage inheritance. It can't guarantee a good design, you still have to do that.

状态可以提供帮助,因为您可以利用继承。它不能保证一个好的设计,你仍然必须这样做。

回答by Zak

Designing a protocol is usually all about the application space you are working within. For instance, http is all about handling web pages, graphics, and posts, while FTP is all about transferring files.

设计一个协议通常都是关于你在其中工作的应用程序空间。例如,http 是关于处理网页、图形和帖子的,而 FTP 是关于传输文件的。

So in short, to start, you should decide what application space you are in, then define the actions that need to be taken. Then finally, before you start designing your actual protocol, you should seriously, seriously hunt for another protocol stack that does what you want to do and avoid implementing a protocol stack altoether. Only after you have determined that something else pre-built absolutely won't work for you should you start building your own protocol stack.

简而言之,首先,您应该确定您所在的应用程序空间,然后定义需要采取的操作。最后,在你开始设计你的实际协议之前,你应该认真地、认真地寻找另一个可以做你想做的事情的协议栈,并避免完全实现一个协议栈。只有在您确定其他预先构建的东西绝对不适合您之后,您才应该开始构建自己的协议栈。

回答by pm100

Finite State Machine is what you want

有限状态机就是你想要的

FSM

有限状态机

So you define a whole bunch of states that you can be in as a receiver or sender (idle, connecting_phase1, connecting_phase2, packet expected,...)

所以你定义了一大堆状态,你可以作为接收者或发送者(空闲,connecting_phase1,connecting_phase2,packet expected,...)

Then define all the possible events (packet1 arrives, net closes, ...)

然后定义所有可能的事件(packet1 到达,网络关闭,...)

finally you have a table that says 'when in state x and event n happens do func y and transition to state q' - for every state and event (many will be null or dups)

最后你有一个表,上面写着“当处于状态 x 和事件 n 发生时,执行 func y 并转换到状态 q” - 对于每个状态和事件(许多将是空的或重复的)

Edit - how to make a FSM (rough sketch)

编辑 - 如何制作 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;

I am sure this is full of invalid syntax - but I hope you get the drift

我确信这充满了无效的语法 - 但我希望你能理解

回答by miro

In C++ you can use Boost::Spirit library to parse your protocol message easily. The only "difficulty" is to define the grammar of your message protocol. Take a look at Gnutella source code to see how they solve this problem. Here http://www9.limewire.com/developer/gnutella_protocol_0.4.pdfis the Gnutella protocol specifications

在 C++ 中,您可以使用 Boost::Spirit 库轻松解析您的协议消息。唯一的“困难”是定义消息协议的语法。看看 Gnutella 源代码,看看他们是如何解决这个问题的。这里http://www9.limewire.com/developer/gnutella_protocol_0.4.pdf是 Gnutella 协议规范

回答by Andres

Why not use XML as your protocol? You can encapsulate and categorize all your pieces of data inside XML nodes

为什么不使用 XML 作为您的协议?您可以在 XML 节点中封装和分类所有数据

回答by Enno Shioji

Can't give you an example myself, but how about looking at how other (competent) people are doing it?

我自己不能给你举个例子,但看看其他(有能力的)人是如何做的怎么样?

Like this one? http://anonsvn.jboss.org/repos/netty/trunk/src/main/java/org/jboss/netty/handler/codec/http/

像这个? http://anonsvn.jboss.org/repos/netty/trunk/src/main/java/org/jboss/netty/handler/codec/http/

P.S. for that matter, I actually recommend using netty as your network framework and build your protocol on top of it. It should be very easy, and you'll probably get rid of bunch of headaches...

PS 就此而言,我实际上建议使用 netty 作为您的网络框架并在其上构建您的协议。它应该很容易,你可能会摆脱一堆头痛......

回答by incarnate

If you are using Java, consider looking at Apache MINA, it's documentation and samples should inspire you in the right way.

如果您使用 Java,请考虑查看Apache MINA,它的文档和示例应该以正确的方式激发您的灵感。

回答by mark

Right-click the network connection icon in the System Tray. Click Troubleshoot problems. The troubleshooter may find and fix the problem, in this case, you can get quickly started with your business. If the troubleshooter can't fix the Winsocks problem, then you may get an error looking like: "One or more network protocols are missing on this computer"

右键单击系统托盘中的网络连接图标。单击疑难解答问题。疑难解答可能会发现并解决问题,在这种情况下,您可以快速开始您的业务。如果疑难解答无法解决 Winsocks 问题,则您可能会收到如下错误消息:“此计算机上缺少一个或多个网络协议”