Создание протокола связи через TCP-сокеты? - PullRequest
0 голосов
/ 02 октября 2011

У меня есть микроконтроллер Arduino с Sparkfun WiFly Shield .

Я создаю простую программу на C # /. NET, которая подключается к Arduino с помощью 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){}
}

На 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
*

Так, как я могу выяснить сообщение, которое пытается отправить ПК?

Я знаю, что мне нужно как-то использовать специальный байт, который будет символизировать конец моего сообщения.(Специальный байт, который я не буду использовать в своем сообщении, только для обозначения конца сообщения)

Но как я могу это сделать?И какой байт использовать?

Ответы [ 2 ]

2 голосов
/ 02 октября 2011

Вы должны разработать свой собственный протокол здесь.Вы должны определить байт (предпочтительно тот, который не будет присутствовать в данных), чтобы указать «начало», и тогда у вас есть три варианта:

  • после начального байта с байтом «длины», указывающимсколько данных для чтения
  • определяют «конечный» байт, который отмечает конец ваших данных
  • считывает данные, пока не получит полное сообщение, которое соответствует одному из тех, которые вы ожидаете

Третий вариант является наименее расширяемым и гибким, конечно, так как если у вас уже есть сообщение «ОТКРЫТО», вы не можете добавить новое сообщение «ОТКРЫТО», например.

Если вы выберете второй вариант и определите «конечный» байт, вам нужно беспокоиться об экранировании этого байта, если это происходит в ваших данных (или использовать другой байт, который гарантированно не будет присутствовать в ваших данных).

0 голосов
/ 02 октября 2011

Глядя на ваш текущий пример, хорошей отправной точкой было бы просто поставить перед каждым сообщением префикс длины.

Если вы хотите поддерживать длинные сообщения, вы можете использовать префикс длиной 2 байта, затем вы прочитаете первые 2 байта, чтобы получить длину, а затем продолжите чтение из сокета, пока не прочитаете указанное количество байтов.по префиксу длины.

Как только вы прочитали полное сообщение, вы вернетесь к ожиданию чтения префикса длины для следующего сообщения и т. д., пока связь не будет прервана одной из сторон.

Конечно, между всем этим вам необходимо проверить наличие ошибок: например, сокет на одном конце закрывается преждевременно и т. Д. И как обрабатывать потенциальные частичные сообщения, которые могут привести к преждевременному закрытию сокета.

...