嵌入式开发两则实用小知识分享
之前为了方便测试部门保存一些测试数据,需要临时开发一个简单的nanomsg server,与板子端的client在局域网内进行通信,接收client数据并保存。关于nanomsg的简单使用介绍可查看往期文章:实用 | 一个高性能通信库的简单使用分享
作为server端,需要绑定电脑的IP,不同的电脑IP是不一样的,所以使用不同的电脑时需要修改IP才能正常使用这个server程序。
在不需要重新编译程序的情况下,有如下两种方法可以满足这个需求: 把IP写在配置文件里,比如ini格式的配置文件里,然后server程序读取配置文件里的IP,再进行绑定。 server程序自动获取IP地址并绑定。
下面分别使用这两种方法: 从配置文件中读取IP地址
配置文件的格式有很多,如JSON、INI等。这里我选用的是INI格式的配置文件,.ini 文件是 Initialization File 的缩写,即初始化文件。INI文件由节、键、值组成,注解使用分号表示(;)。例如:[Section1 Name] KeyName1_1=value1_1 ;这是注释 KeyName1_2=value1_2 [Section2 Name] KeyName2_1=value2_1 KeyName2_2=value2_2
这里我们使用inih解析器来对INI文件进行解析。
inih:一个C 语言编写的 INI 文件解析器。
inih解析器的地址:
https://github.com/benhoyt/inih
同时,inih解析器也已经被收录于大杂烩资源汇总贴中:
https://gitee.com/zhengnianli/EmbedSummary
inih的使用很简单,下面一起来看一下。
下载得到的inih内容如图所示:
把 ini.c 与 ini.h 放到我们的工程下即可。这里我们使用一个测试工程:
同时,新建一个 ip.ini 文件存放于工程目录下。 ip.ini 文件的内容如:[ip] ;Section1 ip_addr = 192.168.1.103 [test] ;Section2 name = ZhengN num = 66
下面我们编写代码test.c来解析这个文件: // 微信公众号:嵌入式大杂烩 #include #include #include #include "ini.h" typedef struct { const char* ip_addr; const char* name; int num; } configuration; static int handler(void* user, const char* section, const char* name, const char* value) { configuration* pconfig = (configuration*)user; #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 if (MATCH("ip", "ip_addr")) { pconfig->ip_addr = strdup(value); } else if (MATCH("test", "name")) { pconfig->name = strdup(value); } else if (MATCH("test", "num")) { pconfig->num = atoi(value); } else { return 0; /* unknown section/name, error */ } return 1; } int main(int argc, char* argv[]) { configuration config; config.ip_addr = NULL; /* set defaults */ config.name = NULL; config.num = 0; if (ini_parse("ip.ini", handler, &config) < 0) { printf("Can"t load "ip.ini" "); return 1; } printf("Config loaded from "ip.ini": ip_addr = %s, name = %s, num = %d ", config.ip_addr, config.name, config.num); if (config.ip_addr) free((void*)config.ip_addr); if (config.name) free((void*)config.name); return 0; }
解析方法很简单(可参考 inih/examples 下的demo,我们这里也是模仿这个demo来做解析的):构造一个配置结构体 configuration ,定义一个configuration结构体用于保存我们解析的数据,结构体里面的成员就是我们需要解析的INI文件里的各个键。例如,我们的ip.ini文件里有ip_addr、name、num这三个键,结构体里的成员表示的就是这三个键。定义一个handler回调函数,用于处理解析过程。解析过程也很简单,匹配Section Name及Key Name,然后取出值即可。 调用 ini_parse 函数对INI文件进行解析。
其中,handler函数里调用了一个 strdup() 函数及 atoi() 函数。strdup()函数是c语言中常用的一种字符串拷贝库函数,一般和free()函数成对出现,,因为strdup()在内部调用了malloc()函数为变量分配内存。 atoi()函数(ascii to integer)是把字符串转换成整型数的一个函数。
编译、运行:
自动获取IP地址
我们可以使用 getifaddrs() 函数来获取。getifaddrs()函数用于获取网卡信息,包括IP、掩码、广播地址等信息。
getifaddrs()函数原型: int getifaddrs (struct ifaddrs **__ifap);__ifap为获取得到的网卡信息。
用getifaddrs()函数获取得到的IP格式为 数值格式(numeric) ,需要转成 表达格式(presentation) 。 inet_ntop() 函数可以满足这个需求。
inet_ntop()函数是随IPv6出现的函数,对于IPv4地址和IPv6地址都适用,函数中p和n分别代表 表达格式(presentation) 和 数值格式(numeric) 。IP地址的表达格式是ASCII字符串,数值格式则是存放到套接字地址结构的二进制值。我们这里需要的就是ASCII字符串形式的IP地址。
inet_ntop()函数原型: const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);family参数:既可以是AF_INET(ipv4)也可以是AF_INET6(ipv6)。 addrptr参数:addrptr指针指向数值格式的IP。 strptr参数:strptr指向表达格式的IP,调用者必须为目标存储单元分配内存并指定其大小。 len参数:容纳表达格式的长度。 返回值:若成功则为指向表达格式的指针,若出错则为NULL。
下面看看实例代码: // 微信公众号:嵌入式大杂烩 #include #include #include #include #include char *get_ip_addr(void) { static char ip_str[256] = {0}; struct ifaddrs *ifaddrs_struct = NULL; void *addrptr = NULL; if (getifaddrs(&ifaddrs_struct) != 0) { printf("getifaddrs error! "); return NULL; } struct ifaddrs *tmp_ifaddrs = ifaddrs_struct; while (tmp_ifaddrs != NULL) { // IPv4 if (tmp_ifaddrs->ifa_addr->sa_family == AF_INET) { #define INET_ADDR_STR_LEN 256 char addr_buf[INET_ADDR_STR_LEN]; addrptr = &((struct sockaddr_in*)tmp_ifaddrs->ifa_addr)->sin_addr; if (inet_ntop(AF_INET, addrptr, addr_buf, INET_ADDR_STR_LEN) == NULL) { printf("inet_ntop error! "); return NULL; } if (strlen(addr_buf) < sizeof(ip_str) - strlen(ip_str)) { strncat(ip_str, addr_buf, strlen(addr_buf)); strncat(ip_str, ";", strlen(";")); } } // IPv6 else if (tmp_ifaddrs->ifa_addr->sa_family == AF_INET6) { } tmp_ifaddrs = tmp_ifaddrs->ifa_next; } freeifaddrs(ifaddrs_struct); return ip_str; } int main(int argc, char** argv) { printf("hello world! "); char *ip_addr = get_ip_addr(); printf("ip addr : %s ", ip_addr); return 0; }
编译、运行:
以上就是本次的分享~
本文讨论: 配置文件大家平时都使用什么格式呢? 获取本机IP地址还有其它方法吗?
欢迎留言讨论~
一个互联网的老兵的2022年的感悟本人是2003年大学毕业,然后2004年就注册了TB网的电商店铺。其实,第一桶金也算是通过互联网工具积累的。先后在TB上开了5个C店,在2012年之前,平均每年纯利润也有7万一个店
学Python怎能不知yield?引言你可能听说过,带有yield的函数在Python中被称之为generator(生成器),又或者都没关注过,Python中还有个yield的存在。如果你了解过Python中的yi
互联网金融整治又添新规如今国内的互联网平台企业,没有一个支付梦,都不好意思称为巨头。支付渠道能帮助平台形成交易闭环,沉淀用户支付数据,进而向信贷理财等其它金融业务延伸。甚至有网友调侃虽然宇宙的尽头未必是
爱柯迪拟发行可转债募资不超16亿元北京商报讯(记者马换换)1月12日晚间,爱柯迪(600933)披露公告称,公司拟公开发行可转换公司债券募集资金不超过16亿元,扣除发行费用后全部用于爱柯迪智能制造科技产业园项目。据
中秋送长辈什么合适?别致又实用的投影仪送礼倍儿有面中秋佳节将至,又是一年团圆节,这次的中秋,你回家过节吗?忙忙碌碌大半年,该是回家看望爸妈的时候了。每年铁打不动的送月饼,今年有没有新花样啊?每年中秋,我和老婆都会给爸妈准备一些实用
继四川禁止挖矿后,下一个挖矿天堂是哪里?6月28日,四川省发布虚拟货币挖矿的清退文件,要求全省立即开展拉网式排查,发现疑似项目立即关停,8月25日前完成,并严禁以任何名义批复虚拟货币挖矿项目。6月20日零点,四川比特币等
任天堂Switch游戏机配件大汇总(配种草指南)任天堂Switch游戏机首发于2017年3月,主机采用家用机掌机一体化的设计。这款游戏机一直都带给用户非常棒的开箱体验,但即使是最好的产品也可以通过正确的配件进行更好的改进。以下列
要不要买激光电视?看完这篇后,我真香了小编每次花重金去电影院看电影时都会思考,要是家里有一个影院级的影音室也太爽了吧!从黑白电视到彩色电视,从LCD电视到液晶屏电视,现在其实已经有了在家也能有影院级体验的激光电视。但是
王文京未来,工业互联网将与企业的厂房一样重要作为工业互联网服务商,用友精智工业互联网平台已连续两年入选工信部双跨平台清单,用友网络董事长兼CEO王文京,在接受中国工业报采访时指出,我国工业互联网发展成效明显,其突出的价值,是
豪华品牌价太高?新势力信不过?纯电SUV不妨看看微蓝7近几年新能源汽车发展迅猛,随着纯电动车型续航的逐步攀升,充电便利性和路权优势的越发明朗,让越来越多的消费者开始认可并愿意选择纯电动车型。据中汽协发布的数据显示2020年国内新能源汽
理想汽车要和增程式死磕到底,是福是祸近日,理想汽车与绵阳新晨动力机械有限公司签署投资协议,双方将成立全新的合资公司四川理想新晨科技有限公司,合资公司将为理想汽车开发并制造全新一代增程器。新款增程器将搭载在理想2022