【问题标题】:simple way of implementing a TCP application built-in shell实现 TCP 应用程序内置 shell 的简单方法
【发布时间】:2014-07-11 14:04:59
【问题描述】:

我想将自己的 shell 嵌入到我的 C++ 可移植应用程序中,该应用程序可以通过 TCP 访问。问题是我真的不知道如何处理控制字符,例如退格符、转义符……我应该考虑实现,比如说,telnet 协议吗?有什么简单的方法可以解决这个问题?

注意:

我知道我正在避开“基于意见”的密切原因,但也许存在一种“规范”的方式,它被广泛用于解决这个问题。

【问题讨论】:

  • Telnet 是一个不错的协议,实现一个基本的 telnet 状态机相对容易。但是,为什么不简单地通过输入,如果您发现删除或退格键击为什么不简单地跳过下一个字符(用于删除)或返回一个字符(用于退格)?
  • 问题是在“客户端控制台”中正确显示某些内容还是在发送此类字符时在服务器中处理套接字数据?
  • @deviantfan 在服务器中处理套接字数据。当然,我想使用普通的 telnet 或其他客户端。

标签: c++ c shell sockets tcp


【解决方案1】:

如果您的目标是实现一个功能齐全的 telnet 服务器(即类似于 Linux 提供的服务器,它可以运行任意命令行程序,并且可以正确处理用户可能想要运行的任何东西,包括伪 GUI 程序,例如NetHack),那么您将别无选择,只能实现大部分或全部RFC 854。 telnet 协议并非微不足道,但它比很多协议都简单,所以做起来可能没有你想象的那么难。

另一方面,如果您不需要“完全的 telnet 兼容性”,而只是想为用户提供一种登录您的程序、向其发送文本命令并读回结果的方式,那就是容易得多——只需让您的程序在一个众所周知的端口上接受 TCP 连接(它甚至可以是默认的 telnet 端口 23,尽管这会阻止在该端口上运行标准的 telnet 守护程序)。您的程序可以通过接受的 TCP 连接简单地发送和接收 ASCII 字符串,这将或多或少适用于任何 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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-30
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多