可靠的全双工串行通信 [英] Reliable full-duplex serial comms

查看:52
本文介绍了可靠的全双工串行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一种设备,该设备将对从 PC 发送的长(假设为无限)数据流进行加密并将其发回.我计划在运行全双工的设备上使用单个串行端口,硬件握手并阻止"数据,在每个块之后发送一个 CRC 值.该设备只会缓冲有限数量的块 - 理想情况下,只有一个缓冲区用于累积正在接收的块,一个缓冲区保存当前正在发送的块,在每个块边界切换它们并使用硬件握手来保持同步.

I'm designing a device that will encrypt a long (assume infinite) stream of data sent from the PC and send it back. I'm planning to use a single serial port on the device running full duplex with hardware handshaking and "block" the data, sending a CRC value after every block. The device will only buffer a limited number of blocks- ideally just one buffer accumulating the block being received and one buffer holding the block presently being sent, switching them over at each block boundary and using hardware handshaking to keep things in sync.

我正在考虑的问题是当出现损坏并且接收器计算的 CRC 值(可能是 PC 或设备)与发送的 CRC 值不匹配时会发生什么.如果接收器检测到错误,它会在其传输线路上设置中断条件 - 因为尽管 TX 和 RX 正在做不同的事情,但我们只能做这些 - 然后我们进入恢复序列.

The problem I'm considering is what happens when there's corruption and there's a mismatch between the CRC value calculated by the receiver- which could be either the PC or the device- and the one sent. If the receiver detects an error, it sets a break condition on its transmit line- because although TX and RX are doing different things that's all we CAN do- and then we drop into a recovery sequence.

在数据从发送方消失之前检测到错误情况时,恢复很容易,但特别是在接收端的 PC 上可能会有大量的缓冲区空间,当 PC 赶上并检测到数据损坏时可能已经从设备中消失了,我们不能简单地重新传输.倒带"密码生成很困难,因此重新发送源数据并尝试在中间提取内容很困难 - 事实上,源数据可能无法重新发送,具体取决于它最终来自何处.

Recovery is easy when the error condition is detected before the data disappears from the sender, but particularly on the PC receiving there may be a significant amount of buffer space, and by the time the PC catches up and detects the corruption the data may have disappeared from the device and we can't simply retransmit. It's difficult to "rewind" cipher generation, so resending the source data and trying to pick things up in the middle is difficult- and indeed the source data may not be available to resend depending on where it's ultimately coming from.

我考虑过让每一方发送它的最后一帧成功接收"计数器以及它最后一帧发送的 CRC 值,如果有太多未确认的数据在输出等待,让设备丢弃 RTS,但这会导致死锁——设备永远不会得到 PC 的接收线程已经赶上的确认.

I considered having each side send its "last frame successfully received" counter along with its last frame sent CRC value, and having the device drop RTS if there's too much unconfirmed data waiting at the output, but that would then deadlock- the device never gets the confirmation that the PC's receive thread has caught up.

我也考虑过让 PC 发送一个块,然后在第一个块被确认处理并接收回之前不发送另一个块,但这基本上是半双工或块同步操作,系统运行速度比它慢可以做.妥协是在设备中有许多缓冲区,PC 知道有多少缓冲区并根据它认为设备正在做什么来限制自己的输出,但在 PC 端似乎需要这种程度的智能"不优雅和老套.

I've also considered having the PC send a block and then not send another block until the first block's been confirmed processed and received back, but that's essentially going to half duplex or block-synchronous operation and the system runs slower than it can do. A compromise is to have a number of buffers in the device, the PC to know how many buffers and to throttle its own output based on what it thinks the device is doing, but having that degree of 'intelligence' needed in the PC side seems inelegant and hacky.

串行通信是一项非常古老的技术.肯定有这样做的好方法吗?

Serial comms is quite ancient tech. Surely there's a good way of doing this?

推荐答案

设计一个可靠的协议并不容易.关于您目前所讨论内容的一些注释:

Designing a reliable protocol is not that easy. Some notes with what you've talked about so far:

  • 只使用 RTS 来做它设计要做的事情,避免接收缓冲区溢出.不适合多做.
  • 强烈考虑不要周围有多个未确认的帧.仅当连接具有高延迟时才重要,这不是串行端口的问题.
  • 通过分层实现全双工操作,以OSI模型为指导.
  • 确保将协议的输入和输出视为纯字节流.成帧只是协议实现的一个细节,实际的帧大小无关紧要.如果应用程序通过使用消息发出信号,那么应该在协议的顶部实现.否则,正确分层的自动结果.
  • 请记住,帧不仅可以传输数据,还可以包括对接收帧的 ACK.换句话说,如果没有任何东西要回传,您只需要一个单独的 ACK 帧.
  • Only use RTS to do what it is designed to do, avoid receive buffer overflow. It is not suitable to do more.
  • Strongly consider not having multiple un-acknowledged frames around. It is only important if the connection suffers from high latency, that is not a problem with serial ports.
  • Achieve full duplex operation by layering, use the OSI model as a guide.
  • Be sure to treat the input and output of your protocol as plain byte streams. Framing is only a detail of the protocol implementation, the actual frame size does not matter. If the app signals by using messages then that should be implemented on top of the protocol. Otherwise the automatic outcome of proper layering.
  • Keep in mind that a frame can do more than just transmit data, it can also include an ACK for a received frame. In other words, you only need a separate ACK frame if there isn't anything to transmit back.

并且避免重新发明轮子,这之前已经完成了.我可以推荐 RATP,它是 RFC916 的主题.顺便说一句,被广泛忽略,因此您不太可能找到可以复制的代码.我已经实施并取得了很好的成功.据我所知,它只有一个缺陷,它对接收缓冲区中存在的多次连接尝试没有弹性.打开端口时有意清除缓冲区很重要.

And avoid reinventing the wheel, this has been done before. I can recommend RATP, the subject of RFC916. Widely ignored btw so you are not likely to find code you can copy. I've implemented it and had good success. It has only one flaw that I know of, it is not resilient to multiple connection attempts that are present in the receive buffer. Intentionally purging the buffer when you open the port is important.

这篇关于可靠的全双工串行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆