在linux下经常要进行socket通信,而数据流多采用目前流行的xml格式,这就会有两个用的比较多的功能:
1、接收端将收到的字符串转换成xml格式的数据;
2、发送端将xml格式的数据转换成字符串发送。
运用libxml2组件进行上述操作实际上是xmlDocPtr和xmlChar两种类型之间的转换。
1. xmlDocPtr -> xmlChar
xmlDocPtr doc;
xmlChar *xmlbuff;
int buffersize;
xmlDocDumpFormatMemory(doc,&xmlbuff,&buffersize,1);
2. xmlChar -> xmlDocPtr
xmlDocPtr doc;
char * cData;
doc = xmlParseMemory(docname,strlen(cData)+1);
怎样把xmlChar转换成char就无须多讲了,直接用(char*)强行转换也行。
注意:要保证 xmlChar到xmlDocPtr转换的成功需要注意一个细节,那就是字符串必须是有用的数具体,类似于<?xml version="1.0" encoding="UTF-8"?>这样的头要去掉
下面的例子,srv端等待6601端口的数据,并使用XML解析,取得其中的name和age项,并打印到终端
client端读取一个XML文件,并把读取的数据转换为字符串,向服务端的端口发送
/*srv.c By ksir in 2011-10-14*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <libxml/parser.h> #include <libxml/xmlmemory.h> #define MAXLINE 80 int port = 6601; /*Port of socket*/ /*parse XML and show content of 'name','age'*/ int parseXML(xmlDocPtr tmpdoc) { //printf("This is in parseXML\n"); xmlNodePtr curNode; /*Keep node of the xml tree*/ xmlChar *szKey; /*Get the root Node from tmpdoc*/ curNode = xmlDocGetRootElement(tmpdoc); /*check the content of the document*/ if (NULL == curNode) { xmlFreeDoc(tmpdoc); return -3; } /*Check the type of the root element*/ if(xmlStrcmp(curNode->name,BAD_CAST"n")) { printf("Document of the wrong type"); xmlFreeDoc(tmpdoc); return -4; } curNode = curNode->xmlChildrenNode; xmlNodePtr propNpdePtr =curNode; while (curNode != NULL) { /*compare element nodes,show the content*/ if( !(xmlStrcmp(curNode->name,(const xmlChar *)"name"))) { szKey = xmlNodeGetContent(curNode); printf("name:%s\n",szKey); xmlFree(szKey); } else if( !(xmlStrcmp(curNode->name,(const xmlChar *)"age"))) { printf("Age:%s\n",xmlNodeGetContent(curNode)); } /*traverse*/ curNode = curNode->next; } xmlFreeDoc(tmpdoc); return 0; } int main(void) { struct sockaddr_in sin; struct sockaddr_in rin; int sock_fd; int address_size; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int len; int n; xmlDocPtr doc; bzero(&sin,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(port); sock_fd = socket(AF_INET,SOCK_DGRAM,0); if (-1 == sock_fd) { perror("call to socket"); exit(1); } n = bind(sock_fd,(struct sockaddr *)&sin,sizeof(sin)); if (-1 == n) { perror("call to bind"); exit(1); } while(1) { address_size = sizeof(rin); n = recvfrom(sock_fd,buf,MAXLINE,(struct sockaddr *)&rin,&address_size); if (-1 == n) { perror("call to recvfrom.\n"); exit(1); } // printf("you ip is %s at port %d:%s\n",// inet_ntop(AF_INET,&rin.sin_addr,str,sizeof(str)),// ntohs(rin.sin_port),(char *)buf); /*transfer buf to xml*/ doc = xmlParseMemory((char *)buf,strlen(buf)+1); if (NULL == doc) { printf("xmlParseMemory fail\n"); return -2; } parseXML(doc); } return 0; }
客户端代码:
/*Client.c by ksir in 2011-10-14*/ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<unistd.h> #include<sys/socket.h> #include<linux/in.h> #include <libxml/parser.h> #include <libxml/xmlmemory.h> int main(int argc,char *argv[]) { if(argc<2){ printf("Please input a file !\n"); exit(0); } int sock; struct sockaddr_in toAddr; struct sockaddr_in fromAddr; unsigned int fromLen; char recvBuffer[128]; sock=socket(AF_INET,IPPROTO_UDP); if(sock<0){ printf("Sock Failed!\n"); exit(1); } memset(&toAddr,sizeof(toAddr)); toAddr.sin_family=AF_INET; toAddr.sin_addr.s_addr=inet_addr("10.11.1.88"); toAddr.sin_port=htons(6601); /*Get the xmlfile and parse into string*/ xmlDocPtr doc; /*file descriptor of the xml*/ xmlChar *xmlbuf; char *szDocName; int buffersize; szDocName = argv[1]; /*Open with GB2312*/ doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER); xmlDocDumpFormatMemory(doc,&xmlbuf,1); printf((char *) xmlbuf); while(1) { sleep(1); if(sendto(sock,xmlbuf,strlen(xmlbuf)+1,(struct sockaddr *)&toAddr,sizeof(toAddr)) == -1){ printf("Sendto Failed!\n"); exit(2); } printf("OK!\n"); } close(sock); }
使用的xml文件:
<n> <name> ksir </name> <age> 18 </age> </n>
使用libxml2库的.c文件的编译:
gcc -o srv ser.c -I /usr/include/libxml2/ -L /usr/local/lib -lxml2
LIBXML2的学习地址:http://www.xmlsoft.org/html/libxml-tree.html