0

我的目标是在 telnet 服务器端使用 C/C++ readline 库,因为它提供了开箱即用的所有必要终端功能。Readline 已经连接到 telnet 套接字,对套接字的读写工作正常。我正在使用Sean Middleditch 的 libtelnet

问题是 readline 输出 '\n' 而不是 '\n\r' 这是一个 telnet 标准去一个新行 = 新行 + 回车。

客户端的当前输出:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
> example
         > another example
                          > 3rd example
                                       > 

预期输出:

Trying 127.0.0.1...
Connected to localhost.
The escape character is '^]'.
> example
> another example
> 3rd example
> 

我阅读文档试图找到一个带有默认换行符的简单变量,但没有这样的东西,或者我一定错过了它。telnet 终端类型也有可能改变这种行为——我还没有到这一步。

你知道如何将这个 '\n' 更改为 '\r\n' 吗?

编辑:

Telnet 启动 & Readline 连接到套接字:

void startLibTelnet(int connfd)
{
    char buffer[512];
    int rs;

    telnet_t *telnet;
        telnet = telnet_init(telopts, _event_handler, 0, &connfd);

    // telnet options
    telnet_negotiate(telnet, TELNET_DO,
            TELNET_TELOPT_LINEMODE);

    telnet_negotiate(telnet, TELNET_WILL,
            TELNET_TELOPT_ECHO);

    telnet_negotiate(telnet, TELNET_WILL,
            TELNET_TELOPT_TTYPE);

    // redirecting readline input/output to TCP socket
    rl_instream = fdopen(connfd, "r");
    rl_outstream = fdopen(connfd, "w");

again:
    // forever loop
    while ( (rs = recv(connfd, buffer, sizeof(buffer), 0)) > 0)
    {
        telnet_recv(telnet, buffer, rs);
    }
    if (rs  < 0 && errno == EINTR)
        goto again;
    else if (rs  < 0)
        perror("str_echo: read error");
}

部分事件处理程序:

static void _event_handler(telnet_t *telnet, telnet_event_t *ev,
                void *user_data)
{
    int sock = *(int*)user_data;

    switch (ev->type) {
    /* data received */
    case TELNET_EV_DATA:
        rl_gets("> ");
        break;
    /* data must be sent */
    case TELNET_EV_SEND:
        _send(sock, ev->data.buffer, ev->data.size);
        break;
    /* request to enable remote feature (or receipt) */
    case TELNET_EV_WILL:
        break;
    /* notification of disabling remote feature (or receipt) */
    case TELNET_EV_WONT:
        break;
    . // here's also 
    . // case DO
    . // case DONT
    default:
        break;
    }
}

我想我应该保留 readline 模块。最好的解决方案可能是告诉客户端将“\n”或换行解释为“\n\r”或换行和回车。我在寻找这种 telnet 选项时遇到问题。

4

1 回答 1

1

应该改变其行为 IMO 的不是 readline,而是应该执行适当翻译的 libtelnet。

libtelnet的文档提到

  • void telnet_send_text(telnet_t *telnet, const char *buffer, size_t size);

根据 RFC854 的要求,发送带有 C 换行符 (\n) 转换为 CR LF 和 C 回车符 (\r) 转换为 CR NUL 的文本字符,除非已协商以 BINARY 模式传输。

所以它应该能够处理这个问题。如果您需要更详细的帮助,您必须展示 readline 如何与 libtelnet 对话。


编辑 - 看起来您正在使用 libtelnet 处理来自 telnet 客户端的输入,但允许 readline 将字符直接放在套接字上返回客户端。这是个错误。根据 libtelnet 文档:

注意:发送到连接远程端的所有数据都必须通过 libtelnet 传递,这一点非常重要。您希望通过线路发送的所有用户输入或过程输出都应提供给以下函数之一。不要直接发送或缓冲未处理的输出数据!

也就是说,你需要

client <-> libtelnet <-> readline

不是

client  -> libtelnet -> readline
   |                       /
    ----------<----------- 

认为这就是你现在正在做的事情。不过我不能确定,因为我不知道如何在您显示的代码之外进行设置connsock

于 2021-03-12T10:08:30.350 回答