Telnet 服务器不会执行我从套接字发送的命令

Posted

技术标签:

【中文标题】Telnet 服务器不会执行我从套接字发送的命令【英文标题】:Telnet server wont execute my command sent from a socket 【发布时间】:2018-06-17 02:03:51 【问题描述】:

您好,我目前正在开发一个向 telnet 服务器发送命令的程序。

这是我的代码:

int _tmain(int argc, _TCHAR* argv[])

    WSAData wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    addrinfo* result;
    int res = getaddrinfo("192.168.56.101", "23", &hints, &result);

    if (res)
    
        std::cout << "failed to getaddrinfo" << std::endl;
    

    SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

    if (connect(sock, result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR && sock != INVALID_SOCKET)
    
        std::cout << "connected";
        char* buf = "md c:\\testfolder\r\n";
        std::cout << send(sock, buf, sizeof("md c:\\testfolder\r\n"), 0);
        const int size = 255;
        char out[size];
        memset(out, 0, size);
        while (true)
        
            res = recv(sock, out, size, 0);
            std::cout << res << std::endl; // this outputs 21
        
    
    else
    

        std::cout << res;
    



    std::cin.get();
    return 0;

发送命令后,telnet 服务器应该在C:\\ directory 中创建一个名为testfolder 的文件夹,但它没有这样做。 recv() 正在向我发送垃圾值。

我已阅读 RFC 854,但它真的很难阅读。所以请向我解释我的代码做错了什么。

【问题讨论】:

首先将out清零,recv的返回值是多少?如果没有发生错误,它应该返回接收到的字节数 @Asesh 返回值为 3。 @Asesh 好。它不是 3. 在我尝试之后。它返回的 21 等于缓冲区的大小 【参考方案1】:

您的代码存在几个问题。最重要的是,如果getaddrinfo() 失败,您将继续执行其余代码,因为result 无效,这些代码将崩溃。而且,您忽略了send()recv() 的返回值。而且您实际上并没有输出您收到的数据。

试试这样的:

int _tmain(int argc, _TCHAR* argv[])

    WSAData wsaData;
    int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (res != 0)
    
        std::cerr << "failed to init Winsock, error " << res << std::endl;
        return 1;
    

    addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    addrinfo* result;

    res = getaddrinfo("192.168.56.101", "23", &hints, &result);
    if (res != 0)
    
        std::cerr << "failed to getaddrinfo, error " << res << std::endl;
        WSACleanup();
        return 1;
    

    SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (sock == INVALID_SOCKET)
    
        res = WSAGetLastError();
        std::cerr << "failed to create socket, error " << res << std::endl;
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    

    if (connect(sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
    
        res = WSAGetLastError();
        std::cerr << "failed to connect, error " << res << std::endl;
        freeaddrinfo(result);
        closesocket(sock);
        WSACleanup();
        return 1;
    

    freeaddrinfo(result);
    std::cout << "connected";

    std::string cmd = "md c:\\testfolder\r\n";

    const char *buf = cmd.c_str();
    int size = cmd.length();
    do
    
        res = send(sock, buf, size, 0);
        if (res == SOCKET_ERROR)
        
            res = WSAGetLastError();
            std::cerr << "failed to send, error " << res << std::endl;
            closesocket(sock);
            WSACleanup();
            return 1;
        
        buf += res;
        size -= res;
    
    while (size > 0);

    char out[255];
    while (true)
    
        res = recv(sock, out, sizeof(out), 0);
        if (res == SOCKET_ERROR)
        
            res = WSAGetLastError();
            std::cerr << "failed to recv, error " << res << std::endl;
            closesocket(sock);
            WSACleanup();
            return 1;
        

        if (res == 0)
        
            std::cout << "disconnected" << std::endl;
            break;
        

        std::cout.write(out, res);
    

    closesocket(sock);
    WSACleanup();

    return 0;

现在,如果您要连接到一个实际 Telnet 服务器,而不仅仅是在标准 Telnet 端口上运行的任意 TCP 服务器,那么您需要实现 实际 Telnet协议。这意味着处理和响应 Telnet 命令(WILLWONT 等)、协商 Telnet 选项(消息缓冲区大小、字符集支持等)等等。 RFC 854 和其他相关 RFC 中描述的所有内容。它可能很难阅读(不是真的),但您需要阅读并理解它。您从服务器收到的“垃圾”可能根本不是垃圾。您还没有解释 Telnet 命令。

简而言之,Telnet 命令是转义的,所以你必须逐字节处理接收到的数据,如果遇到转义字节0xFF,那么下一个字节是命令类型,具体取决于命令是,可能有更多的字节来完成命令。其他不是命令的东西都只是原始数据。

【讨论】:

是的,我有一个实际的 telnet 服务器。 “实现实际的 Telnet 协议”?你的意思是我必须创建自己的服务器应用程序来解析和响应客户端发送的命令?这将破坏远程登录的目的。 @LorenceHernandez 不,您不必创建自己的服务器,您只需要解析并响应您已经连接到的服务器发送给您的内容。不,它不会打败任何东西。 Telnet 和其他协议一样是一个实际的协议。它有自己的语法和规则。 Telnet 不仅仅是发送文本命令。那是 Telnet UI 应用程序通过向您隐藏底层细节来欺骗您。

以上是关于Telnet 服务器不会执行我从套接字发送的命令的主要内容,如果未能解决你的问题,请参考以下文章

通过套接字发送命令,但每次都等待响应(Node.js)

每天一个Linux命令(52)telnet命令

通过 telnet 发送数据而不按回车键

Python套接字客户端:发送数据和接收结果

Python套接字不接收而不发送

通过 telnet 发送击键