没有 super 用户访问权限的 C++ 类 ping 函数

标签 c++ linux sockets ping

我正在尝试编写一个简单的 C++ ping 函数来查看网络地址是否正在响应。我不需要专门的 ICMP,我只需要查看服务器是否存在并响应任何内容。我一直在做一些研究,我提出的每个解决方案都需要创建一个原始套接字或需要程序具有 sudo 访问权限的东西。我无法保证我正在运行的系统能够修改网络堆栈,因此这是无效的。

以下是我已经看过的一些相关问题。

  1. Opening RAW sockets in linux without being superuser
  2. ICMP sockets (linux)
  3. How to Ping Using Sockets Library - C
  4. Why does ping work without administrator privileges?
  5. C++ Boost.asio Ping

看来 ping 需要 super 用户访问是有充分理由的。我不想故意制造安全漏洞,我只是想看看服务器是否有响应。有没有好的 c++ 函数或资源可以做到这一点?我将确保发布我提出的任何示例解决方案。我需要一个 Linux (BSD) 套接字解决方案。由于几乎每个类 unix 系统都运行 SSH,我什至可以只针对端口 22 进行测试。我只打算将 Linux 系统作为一个约束条件。

谢谢

最佳答案

这是一个使用 popen 的例子。我想要一个更好的解决方案,所以如果有一个套接字或其他不求助于 shell 调用的方法,我将不胜感激。这应该仅使用 g++ ping_demo.cpp -o ping_demo 运行。让我知道它是否会导致编译错误。

// C++ Libraries
#include <cstdio>
#include <iostream>
#include <sstream>
#include <string>


/**
 * @brief Convert String to Number
 */
template <typename TP>
TP str2num( std::string const& value ){

    std::stringstream sin;
    sin << value;
    TP output;
    sin >> output;
    return output;
}


/**
 * @brief Convert number to string
 */
template <typename TP>
std::string num2str( TP const& value ){
    std::stringstream sin;
    sin << value;
    return sin.str();
}


/**
 * @brief Execute Generic Shell Command
 *
 * @param[in]   command Command to execute.
 * @param[out]  output  Shell output.
 * @param[in]   mode read/write access
 *
 * @return 0 for success, 1 otherwise.
 *
*/
int Execute_Command( const std::string&  command,
                     std::string&        output,
                     const std::string&  mode = "r")
{
    // Create the stringstream
    std::stringstream sout;

    // Run Popen
    FILE *in;
    char buff[512];

    // Test output
    if(!(in = popen(command.c_str(), mode.c_str()))){
        return 1;
    }

    // Parse output
    while(fgets(buff, sizeof(buff), in)!=NULL){
        sout << buff;
    }

    // Close
    int exit_code = pclose(in);

    // set output
    output = sout.str();

    // Return exit code
    return exit_code;
}


/**
 * @brief Ping
 *
 * @param[in] address Address to ping.
 * @param[in] max_attempts Number of attempts to try and ping.
 * @param[out] details Details of failure if one occurs.
 *
 * @return True if responsive, false otherwise.
 *
 * @note { I am redirecting stderr to stdout.  I would recommend 
 *         capturing this information separately.}
 */
bool Ping( const std::string& address,
           const int&         max_attempts,
           std::string&       details )
{
    // Format a command string
    std::string command = "ping -c " + num2str(max_attempts) + " " + address + " 2>&1";
    std::string output;

    // Execute the ping command
    int code = Execute_Command( command, details );

    return (code == 0);
}


/**
 * @brief Main Function
 */
int main( int argc, char* argv[] )
{
    // Parse input
    if( argc < 2 ){
        std::cerr << "usage: " << argv[0] << " <address> <max-attempts = 3>" << std::endl;
        return 1;
    }

    // Get the address
    std::string host = argv[1];

    // Get the max attempts
    int max_attempts = 1;
    if( argc > 2 ){
        max_attempts = str2num<int>(argv[2]);
    }
    if( max_attempts < 1 ){
        std::cerr << "max-attempts must be > 0" << std::endl;
        return 1;
    }

    // Execute the command
    std::string details;
    bool result = Ping( host, max_attempts, details );

    // Print the result
    std::cout << host << " ";
    if( result == true ){
        std::cout << " is responding." << std::endl;
    }
    else{
        std::cout << " is not responding.  Cause: " << details << std::endl;
    }

    return 0;
}

示例输出

$> g++ ping_demo.cpp -o ping_demo

$> # Valid Example
$> ./ping_demo localhost
localhost  is responding.

$> # Invalid Example
$> ./ping_demo localhostt
localhostt  is not responding.  Cause: ping: unknown host localhostt

$> # Valid Example
$> ./ping_demo 8.8.8.8
8.8.8.8  is responding.

关于没有 super 用户访问权限的 C++ 类 ping 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30356750/

相关文章:

c - VLAN上的UDP套接字单播/多播问题

c++ - 如何将命令行参数转换为 vector ,而每个字符都具有不同的值?

linux - Q文件对话框 : is it possible to filter only executables (under Linux)?

c++ - 这在 C++ 中合法吗?

c - "kill"是如何工作的?特别是 "kill"如何处理被阻止的进程?

ruby-on-rails - 如何使用 Ansible 检查文件中是否存在行?

c++ - 将 IPv4 地址从 ifaddrs 结构分配给 sockaddr_in 结构

python - 通过套接字发送图像时遇到问题

c++ - 编译器错误 undefined symbol

c++ - 打印余数时丢失 0