通过 TCP 套接字创建通信协议?

发布于 2024-12-07 19:27:59 字数 1125 浏览 1 评论 0原文

我有一个带有 Sparkfun WiFly 扩展板 的 Arduino 微控制器。

我在 C#/.NET 中构建了一个简单的程序,使用 System.Net.Sockets 连接到 Arduino:

Socket Soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

public void SendMsg(string msg)
{
    try
    {
        byte[] buffer = StrToByteArray(msg);
        if (Soc.Connected)
            Soc.Send(buffer);
        else
        {
            Soc.Connect(this.remoteIP);
            Soc.Send(buffer);
        }
    }
    catch (Exception e){}
}

在 arduino 上,我有:

while(SpiSerial.available() > 0) {
    byte b = SpiSerial.read();
    Serial.println(b);
}

当套接字连接进行握手时,我得到:“ *OPEN*”,关闭时,我得到:“*CLOS*”。

问题是我一个字节一个字节地获取消息,有时我在一个 while 循环中无法获取完整的消息。

因此,如果我在 Arduino 上使用上面显示的代码,我的串行终端将如下所示:

*
O
P
E
N
*
T
E
S
T
*
C
L
O
S
*

那么我怎样才能找出 PC 试图发送的消息呢?

我知道我需要以某种方式使用一个特殊的字节来象征我的消息的结束。 (一个特殊的字节,我不会在消息中使用,仅象征消息的结束)

但是我该怎么做呢?使用哪个字节?

I have an Arduino microcontroller with a Sparkfun WiFly shield.

I build a simple program in C#/.NET that connects to the Arduino using System.Net.Sockets:

Socket Soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

public void SendMsg(string msg)
{
    try
    {
        byte[] buffer = StrToByteArray(msg);
        if (Soc.Connected)
            Soc.Send(buffer);
        else
        {
            Soc.Connect(this.remoteIP);
            Soc.Send(buffer);
        }
    }
    catch (Exception e){}
}

On the arduino I have:

while(SpiSerial.available() > 0) {
    byte b = SpiSerial.read();
    Serial.println(b);
}

When a socket connection does a handshake, I get: "*OPEN*" and when closed, I get: "*CLOS*".

The problem is that I get the messages one byte by another and sometimes I don't get the full message on one while loop.

So if I use the code I showed above on the Arduino, my serial terminal looks like:

*
O
P
E
N
*
T
E
S
T
*
C
L
O
S
*

So how can I figure out the message the PC is trying to send?

I know I need somehow to use a special byte that will symbolise the end of my message. (A special byte that I won't use in my message, only to symbolise the end of a message)

But how can I do it? And which byte to use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

涫野音 2024-12-14 19:27:59

您需要在这里设计自己的协议。您应该定义一个字节(最好是不会出现在数据中的字节)来指示“开始”,然后您有三种选择:

  • 在开始字节后面跟一个“长度”字节,指示有多少数据
    读取
  • 定义一个“结束”字节,标记数据读取数据的结尾
  • ,直到您拥有与以下之一匹配的完整消息
    当然,

第三个选项是可扩展性和灵活性最低的,就像您已经有一条消息“OPEN”一样,您不能再添加一条新消息“OPENED”。

如果您采用第二个选项并定义一个“结束”字节,那么您需要担心该字节出现在您的数据中时会被转义(或者使用保证不在您的数据中的另一个字节)。

You need to design your own protocol here. You should define a byte (preferably one that won't occur in the data) to indicate "start", and then you have three choices:

  • follow the start byte with a "length" byte indicating how much data
    to read
  • define an "end" byte that marks the end of your data
  • read data until you have a complete message that matches one of
    the ones you expect

The third option is the least extensible and flexible, of course, as if you already have a message "OPEN" you can't then add a new message "OPENED" for instance.

If you take the second option and define an "end" byte then you need to worry about escaping that byte if it occurs within your data (or use another byte that is guaranteed not to be in your data).

薄凉少年不暖心 2024-12-14 19:27:59

看看您当前的示例,一个好的起点是简单地为每条消息添加长度前缀。

如果要支持长消息,可以使用 2 字节长度前缀,然后读取前 2 个字节来获取长度,然后继续从套接字读取,直到读取了长度前缀指示的字节数。

一旦您读完一条完整的消息,您就会返回期望读取下一条消息的长度前缀,依此类推,直到通信被一方终止。

当然,在这一切之间,您需要检查错误情况,例如一端的套接字过早关闭等,以及如何处理可能因套接字过早关闭而导致的潜在部分消息。

Looking at your current example, a good starting point would be to simply prefix each message with a length prefix.

If you want to support long messages you can use a 2 byte length prefix, then you read the first 2 bytes to get the length and then you continue reading from the socket until you have read the number of bytes indicated by the length prefix.

Once you have read a complete message you are then back to expecting to read the length prefix for the next message and so on until the communication is terminated by one of the parties.

Of course in between all this you need to check for error conditions like the socket on one end being closed prematurely etc. and how to handle the potential partial messages that can result form the premature closing of the socket.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文