首页程序设计LinuxC程序linux下另一种实现ping的方法

linux下另一种实现ping的方法

时间2024-09-13 15:41:49发布caterwang分类LinuxC程序浏览357

前面发了一篇:[全场景适应]linux C 实现ping功能-LinuxC程序-凯特网 (caterwang.cn),当时还取了一个名叫全场景,结果后来在ARM ubuntu 下被打脸了,失灵了。于是为了弥补这个缺憾,有了今天这篇文章。

实现方法有点low,但好在有效。以下为源代码

功能函数,这个是一个通用的调用脚本的函数,可以返回执行脚本命令后返回的信息

int execute_cmd (const char *p_cmd, char *p_result, unsigned int cmdTmOut, size_t &resLen)
{
    int len = 0;
    fd_set readfd;
    time_t startTime = time (NULL);
    struct timeval tv;
    int selectRet = HRIM_OK;
    int systemRet = HRIM_OK;
    std::string runCmd = p_cmd;
    size_t res_len = 0;

    FILE * pPipe = popen (runCmd.c_str(), "r");

    if (NULL == pPipe)
    {
        //cout << "popen() failed:"<< strerror(errno) << endl;
        systemRet = HRIM_ERR;
        return systemRet;
    }

    int fd = fileno (pPipe); //FILE描述符转化为FD

    while (true)
    {
        FD_ZERO (&readfd);
        FD_SET (fd, &readfd);

        fcntl (fd, F_SETFD, FD_CLOEXEC);

        /** Select Timeout Hardcode with 1 secs **/
        tv.tv_sec = cmdTmOut;
        tv.tv_usec = 0;

        selectRet = select (fd + 1, &readfd, NULL, NULL, &tv);

        if (selectRet < HRIM_OK)
        {
            //cout << "select() failed " << strerror(errno) << endl;
            snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd select error!");
            systemRet = HRIM_OK;
            break;
        }
        else if (selectRet == HRIM_OK)
        {
            //cout << "select() timeout" << endl;
            snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd:[%s] success!", p_cmd);
            systemRet = HRIM_OK;
            break;
        }
        else
        {
            //cout << "Data is available now" <<endl;
            if (FD_ISSET (fd, &readfd) )
            {
                //if (fgets (buf, sizeof (buf), pPipe) != NULL )
                if (fread ( p_result, sizeof (char), HRI_CMD_RES_LEN, pPipe) > 0)
                {
                    //cout << buf;
                    //strBuf << buf;
                    res_len = strlen (p_result);

                    if (res_len <= 0)
                    {
                        //snprintf (p_result, HRI_CMD_RES_LEN, "RunCmd return empty");
                        snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd:[%s] success!", p_cmd);
                        systemRet = HRIM_OK;
                        break;
                    }

                    len = (res_len - 1); //数组索引从0开始

                    if ( (len > 0) && ( (p_result[len] == '\r') || (p_result[len] == '\n') ) )
                    {
                        p_result[len] = '\0'; //去除结果中的回车换行符
                    }

                    systemRet = HRIM_OK;
                    break;
                }
                else /** No Problem if there is no data ouput by runCmd **/
                {
                    //systemRet = -1;
                    // cout << "fread() failed " << strerror(errno) << endl;
                    //snprintf (p_result, HRI_CMD_RES_LEN, "RunCmd No return value");
                    snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd:[%s] success!", p_cmd);
                    systemRet = HRIM_OK;
                    break;
                }
            }
            else
            {
                // cout << "FD_ISSET() failed " << strerror(errno) << endl;
                snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd:[%s] failed, Error:[%s]",
                          p_cmd, strerror (errno) );
                systemRet = HRIM_OK;
                break;
            }
        }

        /** Check the Script-timeout **/
        if ( (startTime + cmdTmOut) < time (NULL) )
        {
            //    cout<<"Script Timeout"<<endl;
            snprintf (p_result, HRI_CMD_RES_LEN, "ExecuteCmd:[%s] Timeout!", p_cmd);
            systemRet = HRIM_ERR;
            break ;
        }
    }

    pclose (pPipe);
    pPipe = NULL;

    resLen = res_len;
    return systemRet;
}

以下是调用以上函数实现ping功能的函数

//
int FaceCenter::hri_Ping( char *ips, int timeout)  
{ 
    int ret =-1;
    char msg[1024] = {0};
    char cmd[1024] = {0};
    size_t resLen = 0;
	snprintf(cmd, 1024, "ping %s -c 2 | grep received | awk 'NR==1{print $4}'|tr -d ','",ips);
	execute_cmd(cmd, msg, timeout, resLen);
	if(resLen > 0)
	{
		ret = (atoi(msg)==2 ? 0 : 1); //ping 通返回0,ping 不通返回1
	}
	return ret;
}

以下是实现原理简单说明

ping.png


凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!

展开全文READ MORE
pingC++
w5500发热严重?来看看我的方法吧 ubuntu22.04.05 U盘全自动安装--硬盘分区方法

游客 回复需填写必要信息