libxml2库在嵌入式linux中的应用

2019-07-13 00:45发布

    在实际的项目开发过程中,往往有这么一个通用的架构:主应用程序,配置文件,和配置文件控制程序。主应用程序往往是根据配置文件内容来运行的,而控制程序是为给人机交互的。     我也是最近想了解一下这种架构方式,于是在网上找了一些关于配置文件相关的信息,最终确认使用xml文件,因为它比较简单、通用、而功能强大。linux+c最终选择了libxml2库。     关于环境搭建十分简单,参考我的上一篇博客:http://blog.csdn.net/yuanbinquan/article/details/43485323     下面是我使用xml库做的一个简单的demo,demo所针对的问题:在实际的产品中,网络通信(socket)数据是不会打印出来了的,因为完全没这个必要,且浪费系统资源。但是现场维护人员在分析设备问题时,可能需要查看通信层的数据,这样就可以通过应用程序的配置文件参数来决定是否打印通信数据。demo十分粗糙,仅仅实现了该功能,如有不对之处,请各位指正!大力批评 应用程序:两个通信的socket程序 service.c: /*
 gcc -o server server.c -I /home/libxml2-2.9.2/Demo/include/libxml2/ -L /home/libxml2-2.9.2/Demo/lib/ -lxml2
*/

#include  
#include  
#include  
#include  
#include
#include  
#include  
#include  

#include
#include

#define XML_FILE_NAME     "net.xml"
#define DEFAULT_PORT 8000  
#define MAXLINE 4096  


static int CreateDefaultXml()
{
    xmlDocPtr doc;
    xmlNodePtr root_node, NetNode, grandson, GuiNode;
    int nRel;

    doc = xmlNewDoc(BAD_CAST"1.0");
    root_node = xmlNewNode(NULL,BAD_CAST"net.xml");
    
    //设置根节点
    xmlDocSetRootElement(doc,root_node);
    
    /* 网络模块配置 */
    NetNode = xmlNewNode(NULL, BAD_CAST "net");
    xmlAddChild(root_node,NetNode);
    
    grandson = xmlNewNode(NULL, BAD_CAST "print");
    xmlAddChild(NetNode,grandson);
    xmlAddChild(grandson, xmlNewText(BAD_CAST "1"));

    /*GUI 模块配置 */
    GuiNode = xmlNewNode(NULL, BAD_CAST "gui");
    xmlAddChild(root_node,GuiNode);
    
    grandson = xmlNewNode(NULL, BAD_CAST "type");
    xmlAddChild(GuiNode,grandson);
    xmlAddChild(grandson, xmlNewText(BAD_CAST "0x01"));
    
        
    //存储xml文档
    nRel = xmlSaveFile(XML_FILE_NAME,doc);
    if (nRel != -1)
    {
       printf("Create xml file,write %d byte! ", nRel);
    }
    if(nRel == -1)
    {
        printf("Create xml file failed! ");
        return -1;
    }
    //释放文档内节点动态申请的内存
    xmlFreeDoc(doc);
    xmlCleanupParser();
    xmlMemoryDump();

    return 0;
}


static int xmlParse(char * Mode, char *ctl, char *value)
{
    
    xmlDocPtr doc;             //定义解析文档指针
    xmlNodePtr curNode;      //定义结点指针(你需要它为了在各个结点间移动)
    xmlChar *szKey;          //临时字符串变量
    
    doc = xmlReadFile(XML_FILE_NAME,"GB2312",XML_PARSE_RECOVER); //解析文件
    //检查解析文档是否成功,如果不成功,libxml将指一个注册的错误并停止。
    //一个常见错误是不适当的编码。XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存。
    //如果文档是这样,libxml将自动地为你转换到UTF-8。更多关于XML编码信息包含在XML标准中.
    if (NULL == doc)
    {  
       fprintf(stderr,"Document not parsed successfully ");      
       return -1;
    }
    curNode = xmlDocGetRootElement(doc); //确定文档根元素
    /*检查确认当前文档中包含内容*/
    if (NULL == curNode)
    {
       fprintf(stderr,"empty document ");
       xmlFreeDoc(doc);
       return -1;
    }
    /*在这个例子中,我们需要确认文档是正确的类型。"root"是在这个示例中使用文档的根类型。*/
    if (xmlStrcmp(curNode->name, BAD_CAST "net.xml"))
    {
       fprintf(stderr,"document of the wrong type, root node != net.xml");
       xmlFreeDoc(doc);
       return -1;
    }
    curNode = curNode->xmlChildrenNode;
    while(curNode != NULL)
    {
       //取出节点中的内容
       if ((!xmlStrcmp(curNode->name, (const xmlChar *)"net")))
       {
               curNode = curNode->xmlChildrenNode;
            while(curNode != NULL)
            {
               //取出节点中的内容
               if ((!xmlStrcmp(curNode->name, (const xmlChar *)"print")))
               {
                   szKey = xmlNodeGetContent(curNode);
                   //printf("net.xml: %s ", szKey);
                   memcpy(value, szKey, strlen(szKey));
                   xmlFree(szKey);
                   return 0;                       
               }
               curNode = curNode->next;
            }
       }
       curNode = curNode->next;
    }
    xmlFreeDoc(doc);
    return -1;
}


int main(int argc, char** argv)  
{  
    int    socket_fd, connect_fd;  
    struct sockaddr_in     servaddr;
    char     xmlRet[512]={0};
    char    buff[4096];  
    int     n;  
    
    if(access(XML_FILE_NAME, F_OK))
    {
        printf("Create xml file ");
        if(CreateDefaultXml())
        {
            return -1;
        }
    }
    
    //初始化Socket  
    if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){  
    printf("create socket error: %s(errno: %d) ",strerror(errno),errno);  
    exit(0);  
    }  
    //初始化  
    memset(&servaddr, 0, sizeof(servaddr));  
    servaddr.sin_family = AF_INET;  
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。  
    servaddr.sin_port = htons(DEFAULT_PORT);//设置的端口为DEFAULT_PORT  
 
    //将本地地址绑定到所创建的套接字上  
    if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){  
    printf("bind socket error: %s(errno: %d) ",strerror(errno),errno);  
    exit(0);  
    }  
    //开始监听是否有客户端连接  
    if( listen(socket_fd, 10) == -1){  
    printf("listen socket error: %s(errno: %d) ",strerror(errno),errno);  
    exit(0);  
    }  
    printf("======waiting for client's request====== ");  
    while(1){  
    //阻塞直到有客户端连接,不然多浪费CPU资源。  
        if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){  
        printf("accept socket error: %s(errno: %d)",strerror(errno),errno);  
        continue;  
    }  
    //接受客户端传过来的数据  
    n = recv(connect_fd, buff, MAXLINE, 0);  
    //向客户端发送回应数据  
    if(!fork()){ /*紫禁城*/  
        if(send(connect_fd, "Hello,you are connected! ", 26,0) == -1)  
        perror("send error");  
        close(connect_fd);  
        exit(0);  
    }
    memset(xmlRet, 0, sizeof(xmlRet));
    if(!(xmlParse("net", "print", xmlRet)))
    {
        if(xmlRet[0] == '1')
        {
            int iTmp;
            printf("recv data len :%d ",n);
            for(iTmp = 0; iTmp < n; iTmp++)
            {
                if(iTmp % 0x10 == 0)
                {
                    printf(" ");
                }
                if(iTmp % 0x04 == 0)
                {
                    printf(" ");
                }
                printf("%x ", buff[iTmp]);
                
            }
            printf(" ");
        }
    }
    
    /*
        自己的消息处理函数
    */
    close(connect_fd);  
    }  
    close(socket_fd);  
}  

client.c: /*
 gcc -o client client.c
*/
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#define MAXLINE 4096  
 
 
int main(int argc, char** argv)  
{  
    int    sockfd, n,rec_len;  
    char    recvline[4096], sendline[4096];  
    char    buf[MAXLINE];  
    struct sockaddr_in    servaddr;  
 
 
    if( argc != 2){  
    printf("usage: ./client ");  
    exit(0);  
    }  
 
 
    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){  
    printf("create socket error: %s(errno: %d) ", strerror(errno),errno);  
    exit(0);  
    }  
 
 
    memset(&servaddr, 0, sizeof(servaddr));  
    servaddr.sin_family = AF_INET;  
    servaddr.sin_port = htons(8000);  
    if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){  
    printf("inet_pton error for %s ",argv[1]);  
    exit(0);  
    }  
 
 
    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    {  
        printf("connect error: %s(errno: %d) ",strerror(errno),errno);  
        exit(0);  
    }  
 

    printf("send msg to server: ");  
    fgets(sendline, 4096, stdin);  
    if( send(sockfd, sendline, strlen(sendline), 0) < 0)  
    {  
        printf("send msg error: %s(errno: %d) ", strerror(errno), errno);  
        exit(0);  
    }  
    if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) {  
       perror("recv error");  
       exit(1);  
    }  
    buf[rec_len]  = '