простой способ реализации встроенной оболочки приложения TCP

0

Я хотел бы встроить свою собственную оболочку в свое портативное приложение C++, которое будет доступно через TCP. Проблема в том, что я не знаю, как обрабатывать управляющие символы, такие как backspace, escape... Должен ли я изучать реализацию, скажем, протокола telnet? Какой простой способ решить эту проблему?

ЗАМЕТКА:

Я знаю, что я обойду "основанную на мнениях" близкую причину, но, возможно, существует "канонический" способ, который широко используется для решения этой проблемы.

  • 0
    Telnet - это хороший протокол, и относительно легко реализовать базовый конечный автомат telnet. Однако, почему бы просто не пройти через ввод, и если вы найдете нажатие клавиши удаления или возврата, почему бы просто не пропустить следующий символ (для удаления) или вернуться назад на один символ (для возврата)?
  • 0
    Проблема в том, чтобы правильно отображать некоторые вещи в «клиентской консоли» или обрабатывать данные сокетов на сервере, если такие символы отправляются?
Показать ещё 1 комментарий
Теги:
sockets
tcp

1 ответ

2
Лучший ответ

Если ваша цель - реализовать полностью функциональный сервер telnet (то есть аналогичный тому, который предоставляется Linux, который может запускать произвольные программы командной строки и может корректно обрабатывать все, что может потребоваться пользователю, включая программы псевдо-GUI, такие как NetHack) то у вас не будет выбора, кроме как реализовать большинство или все RFC 854. Протокол telnet не является тривиальным, но он проще, чем множество протоколов, поэтому это может быть не так сложно, как вы думаете.

С другой стороны, если вам не нужна "полная совместимость с telnet", а просто хотите предоставить пользователю возможность войти в вашу программу, отправить ему текстовые команды и прочитать результаты, что намного проще - только ваша программа принимает TCP-соединения на хорошо известном порту (это может быть даже порт telnet по умолчанию 23, хотя это предотвратит запуск стандартного демона telnet на этом порту). Ваша программа может просто отправлять и получать строки ASCII по принятому TCP-соединению (-ам), и это будет более или менее работать с любым telnet-клиентом, поскольку протокол telnet предназначен для деградации изящно и, следовательно, будет работать в основном режиме, даже если программа на одном конце соединения не отвечает ни на один из специальных команд-кодов telnet.

Одна из незначительных проблем с просто слепое получение байтов из telnet-клиента заключается в том, что любые командные коды, поступающие от клиента telnet, могут смутить ваш текстовый парсер. Если это проблема для вас, вы можете сделать что-то подобное, чтобы отфильтровать их из данных recv() ', как раз перед тем, как передать этот буфер данных в вашу программу разбора текста программы:

// Rewrites a C character buffer in-place to remove any telnet command-codes from it
// @param buf Pointer to a buffer of data bytes just recv()'d from the telnet client
// @param bufLen The number of valid bytes that (buf) is pointing to
// @returns the number of valid data bytes that (buf) is pointing to after control codes were removed 
int FilterInputBuffer(char * buf, int bufLen)
{
   // persistent state variables, for the case where a telnet command gets split
   // up across several incoming data buffers
   static bool _inSubnegotiation = false;
   static int _commandBytesLeft = 0;

   // Based on the document at http://support.microsoft.com/kb/231866
   static const unsigned char IAC = 255;
   static const unsigned char SB  = 250;
   static const unsigned char SE  = 240;

   char * output = buf;
   for (int i=0; i<bufLen; i++) 
   {
      unsigned char c = buf[i];
      bool keepChar = ((c & 0x80) == 0);
      switch(c)
      {
         case IAC: _commandBytesLeft = 3;                            break;
         case SB:  _inSubnegotiation = true;                         break;
         case SE:  _inSubnegotiation = false; _commandBytesLeft = 0; break;
      }
      if (_commandBytesLeft > 0) {--_commandBytesLeft; keepChar = false;}
      if (_inSubnegotiation) keepChar = false;
      if (keepChar) *output++ = c;  // strip out any telnet control/escape codes
   }
   return (output-buf);  // return new (possibly shorter) data-buffer length
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню