我想将自己的shell嵌入到我的C ++便携式应用程序中,该应用程序可以通过TCP访问。问题是我真的不知道如何处理控制字符,例如退格,逃避......我应该考虑实施,比如telnet协议吗?有什么简单的方法可以解决这个问题?
注:
我知道我正在避开以#34;意见为基础的"关键的原因,但也许存在一个"规范"方式,广泛用于解决这个问题。
答案 0 :(得分:2)
如果您的目标是实现一个功能齐全的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
}