简体   繁体   English

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

[英]Creating communication protocol over TCP Sockets?

I have an Arduino microcontroller with a Sparkfun WiFly shield . 我有一个带有Sparkfun WiFly屏蔽的Arduino微控制器。

I build a simple program in C#/.NET that connects to the Arduino using System.Net.Sockets : 我在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){}
}

On the arduino I have: 关于arduino我有:

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* ". 当套接字连接进行握手时,我得到:“ * OPEN * ”,当关闭时,我得到:“ * 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. 问题是我将消息逐个字节地获取,有时我在一个while循环中没有得到完整的消息。

So if I use the code I showed above on the Arduino, my serial terminal looks like: 因此,如果我使用上面在Arduino上显示的代码,我的串行终端看起来像:

*
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? 那么我该如何找出PC试图发送的消息呢?

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? 要使用哪个字节?

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 跟随起始字节,其中“length”字节表示要读取的数据量
  • 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. 第三种选择是最不可扩展和灵活的,当然,好像你已经有一条消息“OPEN”,你就不能再添加一条新消息“OPENED”了。

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). 如果你选择第二个选项并定义一个“结束”字节,那么你需要担心如果它出现在你的数据中(或使用保证不在你的数据中的另一个字节),则转义该字节。

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. 如果要支持长消息,可以使用2字节长度的前缀,然后读取前2个字节以获取长度,然后继续从套接字读取,直到读取长度前缀指示的字节数。

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. 当然,在所有这些之间,您需要检查错误情况,例如一端的套接字过早关闭等,以及如何处理可能导致套接字过早关闭的潜在部分消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM