使用 .Net 的 NetworkStream.Read/BeginRead 分隔应用程序协议帧
我的问题对于网络编程来说更普遍,但因为我正在尝试编写一个Modbus TCP服务器(从机),所以我将用它来说明我的问题。
在 Modbus TCP 帧中,帧的第 5 个和第 6 个字节给出了帧的大小:
字节 1 & 2:交易ID
字节 3 & 4:协议ID
字节 5 & 6:帧中剩余多少字节
字节 7 - n:帧的其余部分。
使用 NetworkStream.Read()
/BeginRead()
时,如何分隔接收到的帧?
我见过一些开源实现,它们只读取前 6 个字节,解析字节 5 和 6 以获取帧其余部分的大小,然后读取帧的其余部分。但是,如果框架中没有开始和结束分隔符,您如何知道框架的开始和结束位置?
例如,客户端可能发送了一些垃圾字符,然后发送了一个好的帧。在这种情况下,如果我只读取前 6 个字节,我将错过好的帧,并且可能会错过未来的帧,因为我与客户端的节奏不同步。
这个问题并不是特定于 Modbus,而是特定于任何使用“大小”字段来指定帧大小的协议。你如何界定框架?
我觉得我错过了网络编程的一些基本知识,但也许协议设计得不好。
My question is more general to network programming, but because I'm trying to write a Modbus TCP server (slave), I will use it to illustrate my question.
In a Modbus TCP frame, the 5th and 6th byte of the frame give the size of the frame:
bytes 1 & 2: Transaction Id
bytes 3 & 4: Protocol Id
bytes 5 & 6: How many bytes remain in the frame
bytes 7 - n: The rest of the frame.
When using NetworkStream.Read()
/BeginRead()
, how can I delimit the received frames?
I've seen some open source implementations that just read the first 6 bytes, parse bytes 5 and 6 to get the size of the rest of the frame, and then read the rest of the frame. But if you don't have start and end delimiters in your frame, how do you know where the frame begins and ends?
For example, maybe the client sent a few garbage characters, then sent a good frame. In this case if I just read the first 6 bytes, I'll miss the good frame, and possibly future frames because I'm out of sync with the rhythm of the client.
This question isn't really specific to Modbus, but to any protocol that uses a "size" field to specify the size of the frame. How do you delimit the frames?
I feel like I'm missing something fundamental to network programming, but maybe the protocol is just not well-designed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在大多数 Internet 协议中,客户端不应发送垃圾字符:如果客户端发送垃圾字符,服务器将发送错误并关闭连接。如果客户端想要继续与服务器通信,则需要创建一个新连接并这次正常运行。
有一些协议使用自同步代码。这允许接收者从流中的任何位置找到下一帧的开始。
Clients are not supposed to send garbage characters in most Internet protocols: If a client sends garbage, the server will send an error and close the connection. If the client wants to continue communicating with the server, it needs to create a new connection and behave properly this time.
There a some protocols that use a Self-synchronizing code. This allows a recipient to find the start of the next frame from any position within the stream.