通过获取IP地址熟悉popen、str*系列、snprintf()、fgets

本文介绍如何利用popen()函数结合其他字符串处理函数获取网络接口的IP地址及子网掩码,涵盖popen(), snprintf(), fgets(), strstr(), strchr() 和 strrchr()等函数的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过获取IP和网关的代码来学习popen().str*系列等函数的使用


/*********************************************************************************
 *      Copyright:  (C) 2017 LingYun Lab.
 *                  All rights reserved.
 *
 *       Filename:  ifcfg.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(05/16/2017)
 *         Author:  lingyun <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "05/16/2017 06:59:54 PM"
 *                 
 ********************************************************************************/

#include <string.h>
#include <stdio.h>
#include <errno.h>


#define DEBUG

#define IPADDR_LEN          16//定义这个宏的长度为16
#define NIC                 "eth0"//定义NIC为“eth0”

int get_nic_ipaddr(char *nic, char *ipaddr, char *netmask);//声明函数

int main (int argc, char **argv)
{
    char         ipaddr[IPADDR_LEN];
    char         netmask[IPADDR_LEN];


    if( get_nic_ipaddr(NIC, ipaddr, netmask) < 0 )//如果函数的返回值小于0,就表示获取失败
    {
        printf("get IP address for network card %s failure\n", NIC);
        return -1;
    }

    printf("Network card [%s] IPaddr: <%s> Netmask: <%s>\n", NIC, ipaddr, netmask);//打印ip和netmask信息
    return 0;
} /* ----- End of main() ----- */


/* Description:  This function used to get NIC $nic IP address and netmask
 * Input args:  nic: get which Network interface card ipaddress or netmask
 * Output args: ipaddr: the NIC IP address  netmask: the NIC netmask
 * Return Value:  0: Success   <0: Failure
 */
int get_nic_ipaddr(char *nic, char *ipaddr, char *netmask)
{
    FILE               *fp;
    char               command[32];
    char               buf[256];
    char               *p1;
    char               *p2;
    int                rv = -1;

#ifdef DEBUG
    printf("time: %s %s %s %d %s()\n", __DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__ );
#endif


    if( !nic || !ipaddr )//判断这两个参数是否定义
    {
        printf("invalid input arguments\n");//输入的参数无效
        return -1;
    }

    snprintf(command, sizeof(command), "ifconfig %s", nic);//把"ifconfig eth0"命令存放到command数组里
    printf("command: %s\n", command);//打印command中的字符串


    fp=popen(command, "r");//打开一个进程执行命令command,r表示可以读取该进程下的标准输出内容,fp指向该进程
    if( NULL == fp)
    {
        printf("popen() for command %s failure: %s\n", command, strerror(errno));//popen失败
        return -2;
    }

    while( fgets(buf, sizeof(buf), fp) )//把fp指向的进程中的内容存储到buf中
    {
        if( NULL!= (p1=strstr(buf, "inet addr:")) )//用strstr函数在buf中查找inet addr的位置,记录在p1中
        {
            p2 = strchr(p1, ':');//如果找到inet addr ,就继续找":",把位置记录在p2中
            if(p2 == NULL)//如果p2为空,则没有ip信息
                break;

            p2++;//找到":"之后,p2指向":"后的字符串的地址

            p1 = strchr(p2, ' ');//在p2中查找"空格",把地址记录在p1中
            if(p1 == NULL)
                break;

            strncpy(ipaddr, p2, p1-p2);//把从p2地址开始到p1-p2大小的内容拷贝到ipaddr中,就是把找到的ip信息保存到ipaddr中
            rv = 0;

            if( netmask )//继续查找子网掩码信息
            {
 testip.c                                                                                                                           
                rv = -1;
                p2 = strrchr(p1, ':');//我们知道netmask的信息在ip之后,所以从p1记录的地址继续找":",把地址记录在p2中
                if(p2 == NULL)
                    break;

                p2++;//p2指向":"之后的字符

                p1 = strchr(p2, '\n');//在p2中找换行符"\n",把地址记录在p1中
                if(p1 == NULL)
                    break;

                strncpy(netmask, p2, p1-p2);//把从p2开始,p1-p2大小的内容拷贝到netmask中,就是保存子网掩码
                rv = 0;
            }
        }
    }

    pclose(fp);//关闭打开的进程

    return rv;
}




在写代码时,功能复杂的代码,在主函数main()内只负责调用相关函数,比较简洁,对应功能的函数要在开头进行声明,在编写时做一些说明,有助于整理程序。


一、popen()函数


popen()计算机科学中的进程I/O函数,与pclose函数一起使用,必须由 pclose 来终止


头文件

#include <stdio.h>

函数说明

FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );

type 参数只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 "r" 则文件指针连接到 command 的标准输出;如果 type 是 "w" 则文件指针连接到 command 的标准输入。

command 参数是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用-c 标志,shell 将执行这个命令。


二、snprintf()函数

int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);

函数说明: 最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。

函数返回值: 若成功则返回欲写入的字符串长度,若出错则返回负值。

将可变个参数(...)按照format格式化成字符串,然后将其复制到str中。


三、fgets()

函数原型:

char *fgets(char *buf, int bufsize, FILE *stream);

参数:
*buf: 字符型指针,指向用来存储所得数据的地址。
bufsize: 整型数据,指明存储数据的大小。
*stream: 文件结构体指针,将要读取的文件流。


从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize个字符,则读完该行就结束。如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。函数成功将返回buf,失败或读到文件结尾返回NULL。



四、str*系列

头文件

#include<string.h>

strstr()

strstr(string,search [, bool $before_needle = false  ])

strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。


string 规定被搜索的字符串。

search 规定所搜索的字符串


strchr()

strchr函数原型:extern char *strchr(const char *s,char c);

查找字符串s中首次出现字符c的位置。


strrchr()

strrchr(string,char)

查找字符在指定字符串中从左面开始的最后一次出现的位置,如果成功,返回该字符以及其后面的字符,如果失败,则返回 NULL。

string 规定被搜索的字符串。
char 规定要查找的字符。如果该参数是数字,则搜索匹配数字 ASCII 值的字符。如果该参数多于一个字符,则以第一个字符为准。


关于rv要做几点说明,在写程序时,很多时候为了能够及时排除bug,要明确知道程序的每一步执行的情况就要用到rv,返回值来判断,尤其是涉及到子函数,因为很多时候主函数只是调用子函数,它不能具体掌握子函数的执行情况,这个时候返回值就会派上用场。

还有就是csdn博客格式有些问题,代码排版不太好。有时间我再来改吧。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值