在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*)强行转换也行。
下面的例子,srv端等待6601端口的数据,并使用XML解析,取得其中的name和age项,并打印到终端
client端读取一个XML文件,并把读取的数据转换为字符串,向服务端的端口发送
[cpp]
view plain
copy
/*srv.c By ksir in 2011-10-14*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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,0,(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;
}
客户端代码:
[cpp]
view plain
copy
/*Client.c by ksir in 2011-10-14*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
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,SOCK_DGRAM,IPPROTO_UDP);
if(sock<0){
printf("Sock failed!\n");
exit(1);
}
memset(&toAddr,0,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, &buffersize, 1);
printf((char *) xmlbuf);
while(1)
{
sleep(1);
if(sendto(sock,xmlbuf,strlen(xmlbuf)+1,0,(struct sockaddr *)&toAddr,sizeof(toAddr)) == -1){
printf("Sendto failed!\n");
exit(2);
}
printf("OK!\n");
}
close(sock);
} 使用的XML文件:
[html]
view plain
copy
ksir
18
使用libxml2库的.c文件的编译:
gcc -o srv ser.c -I /usr/include/libxml2/ -L /usr/local/lib -lxml2