Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2257492
  • 博文数量: 862
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10598
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(862)

文章存档

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: 嵌入式

2010-04-07 16:16:10

去年在博客里发这个贴时,只将主程序代码贴了出来,导致信息不完整,让读者根本无法进行实验。为此,现将全部代码贴出来,为想在linux下开发基于短信猫的短信收发程序的朋友提供一点参考。
    首先,我根据功能需要创建了几个头文件,一个是stringex.h,包含一些字符串辅助函数;一个是inifile.h,包含读写类似windows环境下ini文件的函数;一个是daemon.h,包含创建linux守护进程(类似windows后台程序)的函数,还有一个是sms.h,包含串口通信相关函数,具体代码如下:
    一、stringex.h,自定义字符串辅助函数库:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:stringex.c 
    功能说明:字符串增强函数库 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#include   
#include   
#include   
 
#ifndef STRING_EX_DEF  
#define STRING_EX_DEF  
const STRING_EX_BUFFER_SIZE=1023;  
 
//定义自定义数据类型  
typedef unsigned char BYTE;  
typedef unsigned char *LPBYTE;  
 
void ltrim(BYTE *outbuff,BYTE *inbuff); //截去左边的空格  
void rtrim(BYTE *outbuff,BYTE *inbuff); //截去右边的空格  
void alltrim(BYTE *outbuff,BYTE *inbuff); //截去左右的空格  
void substr(BYTE *outbuff,BYTE *inbuff,int start,int length); //取子字符串  
int instr(int start,BYTE *inbuff,BYTE *strfind); //查找在字符串inbuff中出现的strfind字符串位置  
void replace(BYTE *outbuff,BYTE *inbuff,BYTE *strfind,BYTE *strreplace); //用strreplace替换字符串中出现的strfind  
void str2hex(BYTE *outbuff,BYTE *inbuff); //将字符串转换成16进制  
void hex2str(BYTE *outbuff,BYTE *inbuff); //将16进制字符串转换成字符串  
int strconv(BYTE *outbuff,const BYTE *inbuff,BYTE *to_Charset,BYTE *from_Charset); //字符集转换(实现各种编码)  
 
void ltrim(BYTE *outbuff,BYTE *inbuff) //截去左边的空格  
{  
    int l;  
    BYTE *p=inbuff;  
 
    while(*p!='\0')  
    {  
        if(32!=(BYTE)*p)break;  
        p++;  
    }  
    l=strlen(inbuff)-(p-inbuff);  
    strncpy(outbuff,p,l);;  
    outbuff[l]='\0';  
}  
 
void rtrim(BYTE *outbuff,BYTE *inbuff) //截去右边的空格  
{  
    int l;  
    BYTE *p=inbuff;  
 
    p+=(strlen(inbuff)-1);  
    while(p>inbuff)  
    {  
        if(32!=(BYTE)*p)break;  
        p--;  
    }  
    strcpy(outbuff,inbuff);  
    outbuff[p-inbuff+1]='\0';  
}  
 
void alltrim(BYTE *outbuff,BYTE *inbuff) //截去左右的空格  
{  
    ltrim(outbuff,inbuff);  
    rtrim(outbuff,inbuff);  
}  
 
void substr(BYTE *outbuff,BYTE *inbuff,int start,int length) //取子字符串  
{  
    if(start<0)start=0;  
    if(length>(strlen(inbuff)-start))length=strlen(inbuff)-start;  
    strncpy(outbuff,inbuff+start,length);  
    outbuff[length]='\0';  
}  
 
int instr(int start,BYTE *inbuff,BYTE *strfind) //查找strfind在字符串inbuff中出现的位置  
{  
    BYTE *p;  
 
    if(strlen(strfind)==1)  
    {  
        p=strchr(inbuff+start,strfind[0]);  
        if(p!=NULL)  
            return p-inbuff;  
        else 
            return -1;  
    }  
    else 
    {  
        p=strstr(inbuff+start,strfind);  
        if(p!=NULL)  
            return p-inbuff;  
        else 
            return -1;  
    }  
}  
 
void replace(BYTE *outbuff,BYTE *inbuff,BYTE *strfind,BYTE *strreplace) //用strreplace替换字符串中出现的strfind  
{  
    BYTE buff[STRING_EX_BUFFER_SIZE];  
    BYTE *p;  
 
    sprintf(buff,"%s%s",inbuff,strreplace);  
    p=strtok(buff,strfind);  
    outbuff[0]='\0';  
    while(p)  
    {  
        sprintf(outbuff,"%s%s%s",outbuff,p,strreplace);  
        p=strtok(NULL,strfind);  
    }  
    outbuff[strlen(outbuff)-strlen(strreplace)*2]='\0';  
}  
 
void str2hex(BYTE *outbuff,BYTE *inbuff)  
{  
    int i;  
    unsigned long lASCII;  
    BYTE szbuff[STRING_EX_BUFFER_SIZE];  
 
    memset(szbuff,0,STRING_EX_BUFFER_SIZE);  
    for(i=0;i    {  
        lASCII=0;  
        if(inbuff[i] < 0x80) //on BYTE of UTF8  
        {  
            lASCII = inbuff[i];  
            if(lASCII > 0xf)  
                sprintf(szbuff,"%s00%2X",szbuff,lASCII);  
            else 
                sprintf(szbuff,"%s000%1X",szbuff,lASCII);  
        }  
        else if((0xc0 <= inbuff[i]) && (inbuff[i] < 0xe0)) //tow BYTE of UTF8  
        {  
            lASCII = inbuff[i] & 0x1f;  
            lASCII = lASCII <<6;  
            lASCII = lASCII | (inbuff[i+1] & 0x3f);  
            sprintf(szbuff,"%s%2X",szbuff,lASCII);  
            i++;  
        }  
        else if((0xe0 <= inbuff[i]) && (inbuff[i] < 0xf0)) //three BYTE of UTF8  
        {  
            lASCII = inbuff[i] & 0x0f;  
            lASCII = lASCII << 6;  
            lASCII = lASCII | (inbuff[i+1] & 0x3f);  
            lASCII = lASCII <<6;  
            lASCII = lASCII | (inbuff[i+2] & 0x3f);  
            sprintf(szbuff,"%s%2X",szbuff,lASCII);  
            i+=2;  
        }  
        else//if((0x80 <=inbuff[i]) & (inbuff[i] < 0xc0)) //not the first byte of UTF8 BYTEacter  
        {  
            break;  
        }  
    }  
    strcpy(outbuff,szbuff);  
}  
 
void hex2str(BYTE *outbuff,BYTE *inbuff) //将16进制转为字符串  
{  
    int i,iLen=strlen(inbuff);  
    BYTE szASCII[5];  
    BYTE szbuff[iLen];  
    unsigned long lASCII; //4位  
 
    if((iLen % 4)!=0) //如果长度不为4的倍数,则退出  
    {  
        outbuff[0]='\0';  
        return;  
    }  
    szbuff[0]='\0';  
    for(i=0;i    {  
        szASCII[0]=inbuff[i];  
        szASCII[1]=inbuff[i+1];  
        szASCII[2]=inbuff[i+2];  
        szASCII[3]=inbuff[i+3];  
        szASCII[4]='\0';  
        lASCII=strtol(szASCII,'\0',16);  
        if(lASCII <= 0x007f) // on BYTE of UTF8  
        {  
            szASCII[0] = (BYTE)lASCII;  
            szASCII[1]='\0';  
        }  
        else if(lASCII <= 0x07ff) // two BYTE of UTF8  
        {  
            szASCII[1] = 0x80 | (BYTE)(lASCII & 0x003f);  
            szASCII[0] = 0xc0 | (BYTE)((lASCII >> 6) & 0x001f);  
            szASCII[2]='\0';  
        }  
        else // three BYTE of UTF8  
        {  
            szASCII[2] = 0x80 | (BYTE)(lASCII & 0x003f);  
            szASCII[1] = 0x80 | (BYTE)((lASCII >> 6) & 0x003f);  
            szASCII[0] = 0xe0 | (BYTE)((lASCII >> 12) & 0x001f);  
            szASCII[3]='\0';  
        }  
        strcat(szbuff,szASCII);  
    }  
    strcpy(outbuff,szbuff);  
}  
 
int strconv(BYTE *outbuff,const BYTE *inbuff,BYTE *to_Charset,BYTE *from_Charset) //字符集转换(实现各种编码)  
{  
    iconv_t it;  
    size_t inleft=strlen(inbuff)+1;  
    size_t outleft=STRING_EX_BUFFER_SIZE;  
    char buff[STRING_EX_BUFFER_SIZE],*pbuff;  
 
    //打开需要转换的字符集  
    it=iconv_open(to_Charset,from_Charset);  
    if((int)it==-1)  
        return -1;  
 
    //进行转换  
    pbuff=buff;  
    memset(buff,0,STRING_EX_BUFFER_SIZE);  
    if((int)iconv(it,(char**)&inbuff,&inleft,(char**)&pbuff,&outleft)==-1)  
        return -2;  
    else 
        strcpy(outbuff,buff);  
 
    //转换结束  
    iconv_close(it);  
 
    return STRING_EX_BUFFER_SIZE-outleft;  
}  
 
#endif 
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:stringex.c
 功能说明:字符串增强函数库
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#include
#include
#include
#ifndef STRING_EX_DEF
#define STRING_EX_DEF
const STRING_EX_BUFFER_SIZE=1023;
//定义自定义数据类型
typedef unsigned char BYTE;
typedef unsigned char *LPBYTE;
void ltrim(BYTE *outbuff,BYTE *inbuff); //截去左边的空格
void rtrim(BYTE *outbuff,BYTE *inbuff); //截去右边的空格
void alltrim(BYTE *outbuff,BYTE *inbuff); //截去左右的空格
void substr(BYTE *outbuff,BYTE *inbuff,int start,int length); //取子字符串
int instr(int start,BYTE *inbuff,BYTE *strfind); //查找在字符串inbuff中出现的strfind字符串位置
void replace(BYTE *outbuff,BYTE *inbuff,BYTE *strfind,BYTE *strreplace); //用strreplace替换字符串中出现的strfind
void str2hex(BYTE *outbuff,BYTE *inbuff); //将字符串转换成16进制
void hex2str(BYTE *outbuff,BYTE *inbuff); //将16进制字符串转换成字符串
int strconv(BYTE *outbuff,const BYTE *inbuff,BYTE *to_Charset,BYTE *from_Charset); //字符集转换(实现各种编码)
void ltrim(BYTE *outbuff,BYTE *inbuff) //截去左边的空格
{
 int l;
 BYTE *p=inbuff;
 while(*p!='\0')
 {
  if(32!=(BYTE)*p)break;
  p++;
 }
 l=strlen(inbuff)-(p-inbuff);
 strncpy(outbuff,p,l);;
 outbuff[l]='\0';
}
void rtrim(BYTE *outbuff,BYTE *inbuff) //截去右边的空格
{
 int l;
 BYTE *p=inbuff;
 p+=(strlen(inbuff)-1);
 while(p>inbuff)
 {
  if(32!=(BYTE)*p)break;
  p--;
 }
 strcpy(outbuff,inbuff);
 outbuff[p-inbuff+1]='\0';
}
void alltrim(BYTE *outbuff,BYTE *inbuff) //截去左右的空格
{
 ltrim(outbuff,inbuff);
 rtrim(outbuff,inbuff);
}
void substr(BYTE *outbuff,BYTE *inbuff,int start,int length) //取子字符串
{
 if(start<0)start=0;
 if(length>(strlen(inbuff)-start))length=strlen(inbuff)-start;
 strncpy(outbuff,inbuff+start,length);
 outbuff[length]='\0';
}
int instr(int start,BYTE *inbuff,BYTE *strfind) //查找strfind在字符串inbuff中出现的位置
{
 BYTE *p;
 if(strlen(strfind)==1)
 {
  p=strchr(inbuff+start,strfind[0]);
  if(p!=NULL)
   return p-inbuff;
  else
   return -1;
 }
 else
 {
  p=strstr(inbuff+start,strfind);
  if(p!=NULL)
   return p-inbuff;
  else
   return -1;
 }
}
void replace(BYTE *outbuff,BYTE *inbuff,BYTE *strfind,BYTE *strreplace) //用strreplace替换字符串中出现的strfind
{
 BYTE buff[STRING_EX_BUFFER_SIZE];
 BYTE *p;
 sprintf(buff,"%s%s",inbuff,strreplace);
 p=strtok(buff,strfind);
 outbuff[0]='\0';
 while(p)
 {
  sprintf(outbuff,"%s%s%s",outbuff,p,strreplace);
  p=strtok(NULL,strfind);
 }
 outbuff[strlen(outbuff)-strlen(strreplace)*2]='\0';
}
void str2hex(BYTE *outbuff,BYTE *inbuff)
{
 int i;
 unsigned long lASCII;
 BYTE szbuff[STRING_EX_BUFFER_SIZE];
 memset(szbuff,0,STRING_EX_BUFFER_SIZE);
 for(i=0;i {
  lASCII=0;
  if(inbuff[i] < 0x80) //on BYTE of UTF8
  {
   lASCII = inbuff[i];
   if(lASCII > 0xf)
    sprintf(szbuff,"%s00%2X",szbuff,lASCII);
   else
    sprintf(szbuff,"%s000%1X",szbuff,lASCII);
  }
  else if((0xc0 <= inbuff[i]) && (inbuff[i] < 0xe0)) //tow BYTE of UTF8
  {
   lASCII = inbuff[i] & 0x1f;
   lASCII = lASCII <<6;
   lASCII = lASCII | (inbuff[i+1] & 0x3f);
   sprintf(szbuff,"%s%2X",szbuff,lASCII);
   i++;
  }
  else if((0xe0 <= inbuff[i]) && (inbuff[i] < 0xf0)) //three BYTE of UTF8
  {
   lASCII = inbuff[i] & 0x0f;
   lASCII = lASCII << 6;
   lASCII = lASCII | (inbuff[i+1] & 0x3f);
   lASCII = lASCII <<6;
   lASCII = lASCII | (inbuff[i+2] & 0x3f);
   sprintf(szbuff,"%s%2X",szbuff,lASCII);
   i+=2;
  }
  else//if((0x80 <=inbuff[i]) & (inbuff[i] < 0xc0)) //not the first byte of UTF8 BYTEacter
  {
   break;
  }
 }
 strcpy(outbuff,szbuff);
}
void hex2str(BYTE *outbuff,BYTE *inbuff) //将16进制转为字符串
{
 int i,iLen=strlen(inbuff);
 BYTE szASCII[5];
 BYTE szbuff[iLen];
 unsigned long lASCII; //4位
 if((iLen % 4)!=0) //如果长度不为4的倍数,则退出
 {
  outbuff[0]='\0';
  return;
 }
 szbuff[0]='\0';
 for(i=0;i {
  szASCII[0]=inbuff[i];
  szASCII[1]=inbuff[i+1];
  szASCII[2]=inbuff[i+2];
  szASCII[3]=inbuff[i+3];
  szASCII[4]='\0';
  lASCII=strtol(szASCII,'\0',16);
  if(lASCII <= 0x007f) // on BYTE of UTF8
  {
   szASCII[0] = (BYTE)lASCII;
   szASCII[1]='\0';
  }
  else if(lASCII <= 0x07ff) // two BYTE of UTF8
  {
   szASCII[1] = 0x80 | (BYTE)(lASCII & 0x003f);
   szASCII[0] = 0xc0 | (BYTE)((lASCII >> 6) & 0x001f);
   szASCII[2]='\0';
  }
  else // three BYTE of UTF8
  {
   szASCII[2] = 0x80 | (BYTE)(lASCII & 0x003f);
   szASCII[1] = 0x80 | (BYTE)((lASCII >> 6) & 0x003f);
   szASCII[0] = 0xe0 | (BYTE)((lASCII >> 12) & 0x001f);
   szASCII[3]='\0';
  }
  strcat(szbuff,szASCII);
 }
 strcpy(outbuff,szbuff);
}
int strconv(BYTE *outbuff,const BYTE *inbuff,BYTE *to_Charset,BYTE *from_Charset) //字符集转换(实现各种编码)
{
 iconv_t it;
 size_t inleft=strlen(inbuff)+1;
 size_t outleft=STRING_EX_BUFFER_SIZE;
 char buff[STRING_EX_BUFFER_SIZE],*pbuff;
 //打开需要转换的字符集
 it=iconv_open(to_Charset,from_Charset);
 if((int)it==-1)
  return -1;
 //进行转换
 pbuff=buff;
 memset(buff,0,STRING_EX_BUFFER_SIZE);
 if((int)iconv(it,(char**)&inbuff,&inleft,(char**)&pbuff,&outleft)==-1)
  return -2;
 else
  strcpy(outbuff,buff);
 //转换结束
 iconv_close(it);
 return STRING_EX_BUFFER_SIZE-outleft;
}
#endif
 
    二、inifile.h,配置文件读写函数库:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:inifile.h 
    功能说明:配置文件读写函数库 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#ifndef INI_FILE_DEF  
#define INI_FILE_DEF  
 
#include   
#include   
#include   
#include "stringex.h"  
 
struct KEY_INFO  
{  
    BYTE Name[64]; //Key名称  
    BYTE Value[64]; //Key值  
    LPBYTE pComment; //指向Key注释的指针  
};  
 
struct NODE_INFO  
{  
    BYTE Name[64]; //节名称  
    LPBYTE pComment; //节注释  
    int iKeys; //键计数  
    struct KEY_INFO *pKeys; //键数组指针  
};  
 
struct FILE_INFO  
{  
    FILE *hFile; //文件句柄  
    int iNodes; //文件包含的节数  
    struct NODE_INFO *pNodes; //节数组指针  
    struct NODE_INFO *pNode; //当前节指针  
};  
 
struct FILE_INFO *OpenIniFile(char *pFileName); //打开或创建配置文件  
LPBYTE GetKeyValue(struct FILE_INFO *pFile,char *pNodeName,char *pKeyName);  
int CloseIniFile(struct FILE_INFO *pFile); //关闭配置文件  
 
struct FILE_INFO *OpenIniFile(char *pFileName) //打开或创建配置文件  
{  
    int i,j; //临时变量,常常用于循环计数  
    static struct FILE_INFO m_File; //局部静态结构变量  
    int iFileSize=0,iLineType; //iFileSize:文件大小,iLineType:行类型  
    int KEY_SIZE=sizeof(struct KEY_INFO);  
    int NODE_SIZE=sizeof(struct NODE_INFO);  
    BYTE szLineBuff[256]; //szLineText行内容缓冲区  
    LPBYTE pFileText=NULL,pLine=NULL; //pFileText:配置文件内容缓冲区,pLine:行内容指针,p:临时字符串指针  
 
    m_File.hFile=NULL;  
    m_File.iNodes=0;  
    m_File.pNode=NULL;  
    m_File.pNodes=NULL;  
    if((m_File.hFile=fopen(pFileName,"r"))==NULL) //如果文件不存在  
        return(NULL);  
 
    //取文件长度  
    fseek(m_File.hFile,0,SEEK_END);  
    iFileSize=ftell(m_File.hFile);  
    if(iFileSize == 0) //如果长度等于0,返回创建的文件指针  
        return(NULL);  
 
    //读配置文件到缓冲区  
    fseek(m_File.hFile,0,SEEK_SET);  
    pFileText = (char*)malloc(iFileSize+2); //申请内存,大小为文件长度+2(防止内存溢出)  
    memset(pFileText,0,iFileSize+1);  
    i=fread(pFileText,iFileSize,1,m_File.hFile);  
 
    //按行分析配置文件内容  
    pLine=strtok(pFileText,"\n");  
 
    while(pLine!=NULL)  
    {  
        ltrim(szLineBuff,pLine); //去掉左边的空格  
        //判断行的类型,0为空节行,1为节行,2为键值对行,3为节注释行(包括空行和错误行),4为键值对注释行(包括空行和错误行)  
        if(m_File.pNode==NULL) //如果当前指针pNode指向NULL,则为一个空节行  
            iLineType=0;  
        else 
        {  
            if(szLineBuff[0]=='[')  
                iLineType=(instr(1,szLineBuff,"]")>0)?1:3;  
            else 
            {  
                if(instr(1,szLineBuff,"=")>0)  
                    iLineType=2;  
                else 
                    iLineType=(m_File.pNode->iKeys==0)?3:4;  
            }  
        }  
        switch(iLineType)  
        {  
        case 0: //空节行  
            m_File.iNodes=1;  
            m_File.pNodes=malloc(NODE_SIZE);  
            m_File.pNode=m_File.pNodes;  
            m_File.pNode->iKeys=0;  
            m_File.pNode->pKeys=NULL;  
            m_File.pNode->Name[0]='\0';  
            m_File.pNode->pComment=malloc(strlen(pLine)+2);  
            strcpy(m_File.pNode->pComment,pLine);  
            break;  
        case 1: //节行  
            m_File.iNodes++; //节计数加1  
            if(m_File.pNode==NULL)  
                m_File.pNodes=malloc(NODE_SIZE); //申请一个新的节  
            else 
                m_File.pNodes=(struct NODE_INFO *)realloc(m_File.pNodes,NODE_SIZE*m_File.iNodes); //重新申请节  
            m_File.pNode=m_File.pNodes+(m_File.iNodes-1); //将pNode指向当前节  
            m_File.pNode->iKeys=0;  
            m_File.pNode->pKeys=NULL;  
            i=instr(1,szLineBuff,"]");  
            substr(m_File.pNode->Name,szLineBuff,1,i-1);  
            //查找有无行尾节注释  
            i=instr(i+1,szLineBuff,"#");  
            if(i>0) //如果有  
            {  
                m_File.pNode->pComment=malloc(strlen(szLineBuff)-i+2);  
                strcpy(m_File.pNode->pComment,szLineBuff+i);  
            }  
            else 
            {  
                m_File.pNode->pComment=malloc(2);  
                m_File.pNode->pComment[0]='\0';  
            }  
            break;  
        case 2: //键值对行  
            m_File.pNode->iKeys++;  
            if(m_File.pNode->pKeys==NULL)  
                m_File.pNode->pKeys=malloc(KEY_SIZE); //申请一个新的键值对  
            else 
                m_File.pNode->pKeys=(struct KEY_INFO *)realloc(m_File.pNode->pKeys,KEY_SIZE*m_File.pNode->iKeys); //重新申请键值对  
            i=instr(1,pLine,"=");  
            substr(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Name,pLine,0,i);  
            //查找有无行尾注释  
            j=instr(i,pLine,"#");  
            if(j>0) //如果有  
            {  
                substr(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,pLine,i+1,j-i-1);  
                m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment=malloc(strlen(pLine)-j+2);  
                strcpy(m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment,pLine+j);  
            }  
            else 
            {  
                strcpy(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,pLine+i+1);  
                m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment=malloc(2);  
                m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment[0]='\0';  
            }  
            //去掉Key值的左右空格  
            alltrim(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value);  
            break;  
        case 3: //节注释行  
            m_File.pNode->pComment=(LPBYTE )realloc(m_File.pNode->pComment,strlen(m_File.pNode->pComment)+strlen(pLine)+2);  
            sprintf(m_File.pNode->pComment,"%s\n%s",m_File.pNode->pComment,pLine);  
            break;  
        case 4: //键值对注释行  
            i=m_File.pNode->iKeys-1;  
            m_File.pNode->pKeys[i].pComment=(LPBYTE )realloc(m_File.pNode->pKeys[i].pComment,strlen(m_File.pNode->pKeys[i].pComment)+strlen(pLine)+2);  
            sprintf(m_File.pNode->pKeys[i].pComment,"%s\n%s",m_File.pNode->pKeys[i].pComment,pLine);  
        }  
        pLine=strtok(NULL,"\n");  
    }  
    if(pFileText !=NULL)  
        free(pFileText);  
 
//  fclose(m_File.hFile);  
    return(&m_File);  
}  
 
LPBYTE GetKeyValue(struct FILE_INFO *pFile,char *pNodeName,char *pKeyName)  
{  
    int i,j;  
 
    if(strcmp(pFile->pNode->Name,pNodeName)==0) //如果指定的节名称与当前节名称相同  
    {  
        for(i=0;ipNode->iKeys;i++)  
        {  
            if(strcmp(pFile->pNode->pKeys[i].Name,pKeyName)==0)  
                return(pFile->pNode->pKeys[i].Value);  
        }  
    }  
    else 
    {  
        pFile->pNode=pFile->pNodes;  
        for(i=0;iiNodes;i++)  
        {  
            if(strcmp(pFile->pNode->Name,pNodeName)==0)  
            {  
                for(j=0;jpNode->iKeys;j++)  
                {  
                    if(strcmp(pFile->pNode->pKeys[j].Name,pKeyName)==0)  
                        return(pFile->pNode->pKeys[j].Value);  
                }  
                break;  
            }  
            pFile->pNode++;  
        }  
    }  
    return(NULL);  
}  
 
int CloseIniFile(struct FILE_INFO *pFile) //关闭配置文件  
{  
    int i,j;  
    if(pFile->pNodes!=NULL)  
    {  
        pFile->pNode=pFile->pNodes;  
        for(i=0;iiNodes;i++)  
        {  
            free(pFile->pNode->pComment); //释放节注释  
            for(j=0;jpNode->iKeys;j++)  
                free(pFile->pNode->pKeys[j].pComment); //释放键值对注释  
            free(pFile->pNode->pKeys); //释放键值对  
            pFile->pNode++;  
        }  
        free(pFile->pNodes);  
    }  
    fclose(pFile->hFile);  
}  
 
#endif 
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:inifile.h
 功能说明:配置文件读写函数库
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#ifndef INI_FILE_DEF
#define INI_FILE_DEF
#include
#include
#include
#include "stringex.h"
struct KEY_INFO
{
 BYTE Name[64]; //Key名称
 BYTE Value[64]; //Key值
 LPBYTE pComment; //指向Key注释的指针
};
struct NODE_INFO
{
 BYTE Name[64]; //节名称
 LPBYTE pComment; //节注释
 int iKeys; //键计数
 struct KEY_INFO *pKeys; //键数组指针
};
struct FILE_INFO
{
 FILE *hFile; //文件句柄
 int iNodes; //文件包含的节数
 struct NODE_INFO *pNodes; //节数组指针
 struct NODE_INFO *pNode; //当前节指针
};
struct FILE_INFO *OpenIniFile(char *pFileName); //打开或创建配置文件
LPBYTE GetKeyValue(struct FILE_INFO *pFile,char *pNodeName,char *pKeyName);
int CloseIniFile(struct FILE_INFO *pFile); //关闭配置文件
struct FILE_INFO *OpenIniFile(char *pFileName) //打开或创建配置文件
{
 int i,j; //临时变量,常常用于循环计数
 static struct FILE_INFO m_File; //局部静态结构变量
 int iFileSize=0,iLineType; //iFileSize:文件大小,iLineType:行类型
 int KEY_SIZE=sizeof(struct KEY_INFO);
 int NODE_SIZE=sizeof(struct NODE_INFO);
 BYTE szLineBuff[256]; //szLineText行内容缓冲区
 LPBYTE pFileText=NULL,pLine=NULL; //pFileText:配置文件内容缓冲区,pLine:行内容指针,p:临时字符串指针
 m_File.hFile=NULL;
 m_File.iNodes=0;
 m_File.pNode=NULL;
 m_File.pNodes=NULL;
 if((m_File.hFile=fopen(pFileName,"r"))==NULL) //如果文件不存在
  return(NULL);
 //取文件长度
 fseek(m_File.hFile,0,SEEK_END);
 iFileSize=ftell(m_File.hFile);
 if(iFileSize == 0) //如果长度等于0,返回创建的文件指针
  return(NULL);
 //读配置文件到缓冲区
 fseek(m_File.hFile,0,SEEK_SET);
 pFileText = (char*)malloc(iFileSize+2); //申请内存,大小为文件长度+2(防止内存溢出)
 memset(pFileText,0,iFileSize+1);
 i=fread(pFileText,iFileSize,1,m_File.hFile);
 //按行分析配置文件内容
 pLine=strtok(pFileText,"\n");
 while(pLine!=NULL)
 {
  ltrim(szLineBuff,pLine); //去掉左边的空格
  //判断行的类型,0为空节行,1为节行,2为键值对行,3为节注释行(包括空行和错误行),4为键值对注释行(包括空行和错误行)
  if(m_File.pNode==NULL) //如果当前指针pNode指向NULL,则为一个空节行
   iLineType=0;
  else
  {
   if(szLineBuff[0]=='[')
    iLineType=(instr(1,szLineBuff,"]")>0)?1:3;
   else
   {
    if(instr(1,szLineBuff,"=")>0)
     iLineType=2;
    else
     iLineType=(m_File.pNode->iKeys==0)?3:4;
   }
  }
  switch(iLineType)
  {
  case 0: //空节行
   m_File.iNodes=1;
   m_File.pNodes=malloc(NODE_SIZE);
   m_File.pNode=m_File.pNodes;
   m_File.pNode->iKeys=0;
   m_File.pNode->pKeys=NULL;
   m_File.pNode->Name[0]='\0';
   m_File.pNode->pComment=malloc(strlen(pLine)+2);
   strcpy(m_File.pNode->pComment,pLine);
   break;
  case 1: //节行
   m_File.iNodes++; //节计数加1
   if(m_File.pNode==NULL)
    m_File.pNodes=malloc(NODE_SIZE); //申请一个新的节
   else
    m_File.pNodes=(struct NODE_INFO *)realloc(m_File.pNodes,NODE_SIZE*m_File.iNodes); //重新申请节
   m_File.pNode=m_File.pNodes+(m_File.iNodes-1); //将pNode指向当前节
   m_File.pNode->iKeys=0;
   m_File.pNode->pKeys=NULL;
   i=instr(1,szLineBuff,"]");
   substr(m_File.pNode->Name,szLineBuff,1,i-1);
   //查找有无行尾节注释
   i=instr(i+1,szLineBuff,"#");
   if(i>0) //如果有
   {
    m_File.pNode->pComment=malloc(strlen(szLineBuff)-i+2);
    strcpy(m_File.pNode->pComment,szLineBuff+i);
   }
   else
   {
    m_File.pNode->pComment=malloc(2);
    m_File.pNode->pComment[0]='\0';
   }
   break;
  case 2: //键值对行
   m_File.pNode->iKeys++;
   if(m_File.pNode->pKeys==NULL)
    m_File.pNode->pKeys=malloc(KEY_SIZE); //申请一个新的键值对
   else
    m_File.pNode->pKeys=(struct KEY_INFO *)realloc(m_File.pNode->pKeys,KEY_SIZE*m_File.pNode->iKeys); //重新申请键值对
   i=instr(1,pLine,"=");
   substr(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Name,pLine,0,i);
   //查找有无行尾注释
   j=instr(i,pLine,"#");
   if(j>0) //如果有
   {
    substr(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,pLine,i+1,j-i-1);
    m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment=malloc(strlen(pLine)-j+2);
    strcpy(m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment,pLine+j);
   }
   else
   {
    strcpy(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,pLine+i+1);
    m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment=malloc(2);
    m_File.pNode->pKeys[m_File.pNode->iKeys-1].pComment[0]='\0';
   }
   //去掉Key值的左右空格
   alltrim(m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value,m_File.pNode->pKeys[m_File.pNode->iKeys-1].Value);
   break;
  case 3: //节注释行
   m_File.pNode->pComment=(LPBYTE )realloc(m_File.pNode->pComment,strlen(m_File.pNode->pComment)+strlen(pLine)+2);
   sprintf(m_File.pNode->pComment,"%s\n%s",m_File.pNode->pComment,pLine);
   break;
  case 4: //键值对注释行
   i=m_File.pNode->iKeys-1;
   m_File.pNode->pKeys[i].pComment=(LPBYTE )realloc(m_File.pNode->pKeys[i].pComment,strlen(m_File.pNode->pKeys[i].pComment)+strlen(pLine)+2);
   sprintf(m_File.pNode->pKeys[i].pComment,"%s\n%s",m_File.pNode->pKeys[i].pComment,pLine);
  }
  pLine=strtok(NULL,"\n");
 }
 if(pFileText !=NULL)
  free(pFileText);
// fclose(m_File.hFile);
 return(&m_File);
}
LPBYTE GetKeyValue(struct FILE_INFO *pFile,char *pNodeName,char *pKeyName)
{
 int i,j;
 if(strcmp(pFile->pNode->Name,pNodeName)==0) //如果指定的节名称与当前节名称相同
 {
  for(i=0;ipNode->iKeys;i++)
  {
   if(strcmp(pFile->pNode->pKeys[i].Name,pKeyName)==0)
    return(pFile->pNode->pKeys[i].Value);
  }
 }
 else
 {
  pFile->pNode=pFile->pNodes;
  for(i=0;iiNodes;i++)
  {
   if(strcmp(pFile->pNode->Name,pNodeName)==0)
   {
    for(j=0;jpNode->iKeys;j++)
    {
     if(strcmp(pFile->pNode->pKeys[j].Name,pKeyName)==0)
      return(pFile->pNode->pKeys[j].Value);
    }
    break;
   }
   pFile->pNode++;
  }
 }
 return(NULL);
}
int CloseIniFile(struct FILE_INFO *pFile) //关闭配置文件
{
 int i,j;
 if(pFile->pNodes!=NULL)
 {
  pFile->pNode=pFile->pNodes;
  for(i=0;iiNodes;i++)
  {
   free(pFile->pNode->pComment); //释放节注释
   for(j=0;jpNode->iKeys;j++)
    free(pFile->pNode->pKeys[j].pComment); //释放键值对注释
   free(pFile->pNode->pKeys); //释放键值对
   pFile->pNode++;
  }
  free(pFile->pNodes);
 }
 fclose(pFile->hFile);
}
#endif
 
    三、daemon.h,守护进程函数库:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:daemon.h 
    功能说明:实现守护进程 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#ifndef DAEMON_PROCESS_DEF  
#define DAEMON_PROCESS_DEF  
#include   
#include   
#include   
#include   
#include   
#include   
 
void MakeDaemon(char* pLogFileName,int (*pfnMessageLoop)());  
char *GetCurrentDateAndTime(); //辅助函数,获取当前日期和时间  
 
void MakeDaemon(char* pLogFileName,int (*pfnMessageLoop)(FILE *hLog))  
{  
    static FILE *fpLog=NULL; //日志文件指针  
    char szLogInfo[63];  
 
    //忽略I/O信号和STOP信号  
    signal(SIGTTOU,SIG_IGN);  
    signal(SIGTTIN,SIG_IGN);  
    signal(SIGTSTP,SIG_IGN);  
    signal(SIGHUP,SIG_IGN);  
 
    //退出父进程,程序转入后台运行  
    if(fork()!=0)return;  
 
    //创建一个新的会议组  
    if(setsid()<0)return;  
    //退出子进程,让孙进程失去终端控制  
    if(fork()!=0)return;  
 
    //忽略SIGCHLD信号  
    signal(SIGCHLD,SIG_IGN);  
      
    //处理日志文件  
    if(pLogFileName!=NULL)  
    {  
        if((fpLog=fopen(pLogFileName,"r"))==NULL) //如果文件不存在  
            fpLog=fopen(pLogFileName,"w");  
        else 
        {  
            fclose(fpLog);  
            fpLog=fopen(pLogFileName,"a+");  
        }  
    }  
 
    //写日志信息(服务开始)  
    if(fpLog!=NULL)  
    {  
        sprintf(szLogInfo,"服务从【%s】开始运行...\n",GetCurrentDateAndTime());  
        fputs(szLogInfo,fpLog);  
        fflush(fpLog);  
    }  
 
    //调用指定的事件pfnMessageLoop  
    if((*pfnMessageLoop)!=NULL)  
        (*pfnMessageLoop)(fpLog);  
 
    //写日志信息(服务结束)  
    if(fpLog!=NULL)  
    {  
        sprintf(szLogInfo,"服务在【%s】停止运行!\n",GetCurrentDateAndTime());  
        fputs(szLogInfo,fpLog);  
        fflush(fpLog);  
        fclose(fpLog);  
    }  
}  
 
char *GetCurrentDateAndTime()  
{  
    time_t timep;  
    struct tm *p;  
    static char my_date_time[31];  
 
    time(&timep);  
    p=localtime(&timep); //取得当地时间  
    sprintf(my_date_time,"%d年%d月%d日 %d:%d:%d",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);  
    return(my_date_time);  
}  
#endif 
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:daemon.h
 功能说明:实现守护进程
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#ifndef DAEMON_PROCESS_DEF
#define DAEMON_PROCESS_DEF
#include
#include
#include
#include
#include
#include
void MakeDaemon(char* pLogFileName,int (*pfnMessageLoop)());
char *GetCurrentDateAndTime(); //辅助函数,获取当前日期和时间
void MakeDaemon(char* pLogFileName,int (*pfnMessageLoop)(FILE *hLog))
{
 static FILE *fpLog=NULL; //日志文件指针
 char szLogInfo[63];
 //忽略I/O信号和STOP信号
 signal(SIGTTOU,SIG_IGN);
 signal(SIGTTIN,SIG_IGN);
 signal(SIGTSTP,SIG_IGN);
 signal(SIGHUP,SIG_IGN);
 //退出父进程,程序转入后台运行
 if(fork()!=0)return;
 //创建一个新的会议组
 if(setsid()<0)return;
 //退出子进程,让孙进程失去终端控制
 if(fork()!=0)return;
 //忽略SIGCHLD信号
 signal(SIGCHLD,SIG_IGN);
 
 //处理日志文件
 if(pLogFileName!=NULL)
 {
  if((fpLog=fopen(pLogFileName,"r"))==NULL) //如果文件不存在
   fpLog=fopen(pLogFileName,"w");
  else
  {
   fclose(fpLog);
   fpLog=fopen(pLogFileName,"a+");
  }
 }
 //写日志信息(服务开始)
 if(fpLog!=NULL)
 {
  sprintf(szLogInfo,"服务从【%s】开始运行...\n",GetCurrentDateAndTime());
  fputs(szLogInfo,fpLog);
  fflush(fpLog);
 }
 //调用指定的事件pfnMessageLoop
 if((*pfnMessageLoop)!=NULL)
  (*pfnMessageLoop)(fpLog);
 //写日志信息(服务结束)
 if(fpLog!=NULL)
 {
  sprintf(szLogInfo,"服务在【%s】停止运行!\n",GetCurrentDateAndTime());
  fputs(szLogInfo,fpLog);
  fflush(fpLog);
  fclose(fpLog);
 }
}
char *GetCurrentDateAndTime()
{
 time_t timep;
 struct tm *p;
 static char my_date_time[31];
 time(&timep);
 p=localtime(&timep); //取得当地时间
 sprintf(my_date_time,"%d年%d月%d日 %d:%d:%d",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
 return(my_date_time);
}
#endif
 
    四、asynccom.h,串口通信函数库:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:asynccom.h 
    功能说明:串口异步通信函数库 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#ifndef ASYNC_COM_DEF  
#define ASYNC_COM_DEF  
 
#include   
#include   
#include   
#include   
 
#define _POSIX_SOURCE 1 //POSIX 系统相容  
   
int OpenComm(int iCommPort); //打开串口设备文件,iCommPort串口端口号,返回句柄  
void CloseComm(int hComm); //关闭设备文件  
int SetCommParam(int hComm,int BaudRate,unsigned char ParityBits,int DataBits,int StopBits); //参数设置,包括:波特率,校验位,停止位,数据位  
int WriteComm(int hComm,char *pBuff); //写串口  
unsigned char *ReadComm(int hComm); //以同步方式读串口  
 
int OpenComm(int iCommPort) //打开串口设备文件,iCommPort串口端口号,返回句柄  
{  
    int hComm;  
    char szCommFileName[127];  
    struct sigaction saio;  
 
    sprintf(szCommFileName,"/dev/ttyS%d",iCommPort-1);  
    hComm=open(szCommFileName,O_RDWR|O_NOCTTY|O_NONBLOCK);//加上O_NONBLOCK:非块模式(专用于命名管道),O_NDELAY:非阻塞模式  
 
    //在使实现异步访问方式前,安装信号处理函数  
    saio.sa_handler = signal_handler_IO;  
    saio.sa_mask = 0;  
    saio.sa_flags = 0;  
    saio.sa_restorer = NULL;  
    sigaction(SIGIO,&saio,NULL);  
 
    //允许进程去接收SIGIO 信号  
    fcntl(hComm, F_SETOWN, getpid());  
 
    //允许串口设备为异步访问  
    fcntl(hComm, F_SETFL, FASYNC);  
 
    return(hComm);  
}  
 
void CloseComm(int hComm) //关闭设备文件  
{  
    tcflush(hComm,TCIOFLUSH); //清空输入输出数据线  
    usleep(100000); //延时100毫秒  
    close(hComm);  
}  
 
int SetCommParam(int hComm,int BaudRate,unsigned char ParityBits,int DataBits,int StopBits)//参数设置,包括:波特率,校验位,停止位,数据位  
{  
    int i;  
    struct termios options;  
    int speed_value[]={B115200,B38400,B19200,B9600,B4800};  
    int speed_name[]={115200,38400,19200,9600,4800};  
 
    tcflush(hComm,TCIOFLUSH);  
 
    tcgetattr(hComm,&options);  
//  bzero(&options,sizeof(struct termios));  
 
    options.c_cflag=(CLOCAL|CREAD|CRTSCTS); //Control options  
    options.c_cflag&=~CSIZE; //Control options  
    options.c_lflag=ICANON; //Local options  
    //options.c_oflag&=~OPOST; //Output options  
    options.c_oflag=0; //Output options,Raw模式  
    options.c_iflag=(IGNPAR|ICRNL); //Input options  
    options.c_cc[VTIME]=0;  
    options.c_cc[VMIN]=1;  
    options.c_cc[VEOF]=4;  
//  options.c_iflag&=~(IXON|IXOFF|IXANY); //Input options  
 
    /*以下为Control characters 
    options.c_cc[VINTR]=0;//Ctrl-c 
    options.c_cc[VQUIT]=0;//Ctrl- 
    options.c_cc[VERASE]=0;//del 
    options.c_cc[VKILL]=0;//@  
    options.c_cc[VEOF]=4;//Ctrl-d 
    options.c_cc[VTIME]=0;//不使用分割字元组的计时器 
    options.c_cc[VMIN]=1;//在读取到 1 个字元前先停止 
    options.c_cc[VSWTC]=0;//'\0' 
    options.c_cc[VSTART]=0; //Ctrl-q 
    options.c_cc[VSTOP]=0; //Ctrl-s 
    options.c_cc[VSUSP]=26; //Ctrl-z 
    options.c_cc[VEOL]=0; //'\0' 
    options.c_cc[VREPRINT]=0; //Ctrl-r 
    options.c_cc[VDISCARD]=0; //Ctrl-u 
    options.c_cc[VWERASE]=0; //Ctrl-w 
    options.c_cc[VLNEXT]=0; //Ctrl-v 
    options.c_cc[VEOL2]=0; //'\0'*/ 
 
    //设置波特率  
    for(i=0;i    {  
        if(BaudRate==speed_name[i])  
        {  
            options.c_cflag|=speed_value[i];  
            break;  
        }  
    }  
 
    //设置校验位  
    switch(ParityBits)  
    {  
        case 'o':case 'O': //奇校验  
            options.c_cflag|=(PARODD|PARENB);  
            options.c_iflag|=INPCK;  
            break;  
        case 'e':case 'E': //偶校验  
            options.c_cflag|=PARENB;  
            options.c_cflag&=~PARODD;  
            options.c_iflag|=INPCK;  
            break;  
        case 's':case 'S': //Space校验  
            options.c_cflag&=~PARENB;  
            options.c_cflag&=~CSTOPB;  
            options.c_iflag|=INPCK;  
            break;  
        default: //默认为无校验,即'n'或'N'  
            options.c_cflag&=~PARENB;  
            options.c_iflag&=~INPCK;  
    }  
 
    //设置数据位  
    if(DataBits==7)  
        options.c_cflag|=CS7;  
    else 
        options.c_cflag|=CS8;  
 
    //设置停止位  
    if(StopBits==1)  
        options.c_cflag&=~CSTOPB;  
    else 
        options.c_cflag|=CSTOPB;  
 
    //清空数据线,并启用新的设置  
    tcflush(hComm,TCIFLUSH);  
    tcsetattr(hComm,TCSANOW,&options);  
 
}  
 
int WriteComm(int hComm,char *pBuff) //写串口  
{  
    int iBytes=0;  
 
    iBytes=write(hComm,pBuff,strlen(pBuff));  
    return(iBytes);  
}  
 
unsigned char *ReadComm(int hComm) //以同步方式读串口  
{  
    int iBytes;  
    static unsigned char szBuff[256]; //数据缓存  
    memset(szBuff,0,256);  
    iBytes=read(hComm,szBuff,256);  
    return(szBuff);  
}  
 
#endif 
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:asynccom.h
 功能说明:串口异步通信函数库
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#ifndef ASYNC_COM_DEF
#define ASYNC_COM_DEF
#include
#include
#include
#include
#define _POSIX_SOURCE 1 //POSIX 系统相容
 
int OpenComm(int iCommPort); //打开串口设备文件,iCommPort串口端口号,返回句柄
void CloseComm(int hComm); //关闭设备文件
int SetCommParam(int hComm,int BaudRate,unsigned char ParityBits,int DataBits,int StopBits); //参数设置,包括:波特率,校验位,停止位,数据位
int WriteComm(int hComm,char *pBuff); //写串口
unsigned char *ReadComm(int hComm); //以同步方式读串口
int OpenComm(int iCommPort) //打开串口设备文件,iCommPort串口端口号,返回句柄
{
 int hComm;
 char szCommFileName[127];
 struct sigaction saio;
 sprintf(szCommFileName,"/dev/ttyS%d",iCommPort-1);
 hComm=open(szCommFileName,O_RDWR|O_NOCTTY|O_NONBLOCK);//加上O_NONBLOCK:非块模式(专用于命名管道),O_NDELAY:非阻塞模式
 //在使实现异步访问方式前,安装信号处理函数
 saio.sa_handler = signal_handler_IO;
 saio.sa_mask = 0;
 saio.sa_flags = 0;
 saio.sa_restorer = NULL;
 sigaction(SIGIO,&saio,NULL);
 //允许进程去接收SIGIO 信号
 fcntl(hComm, F_SETOWN, getpid());
 //允许串口设备为异步访问
 fcntl(hComm, F_SETFL, FASYNC);
 return(hComm);
}
void CloseComm(int hComm) //关闭设备文件
{
 tcflush(hComm,TCIOFLUSH); //清空输入输出数据线
 usleep(100000); //延时100毫秒
 close(hComm);
}
int SetCommParam(int hComm,int BaudRate,unsigned char ParityBits,int DataBits,int StopBits)//参数设置,包括:波特率,校验位,停止位,数据位
{
 int i;
 struct termios options;
 int speed_value[]={B115200,B38400,B19200,B9600,B4800};
 int speed_name[]={115200,38400,19200,9600,4800};
 tcflush(hComm,TCIOFLUSH);
 tcgetattr(hComm,&options);
// bzero(&options,sizeof(struct termios));
 options.c_cflag=(CLOCAL|CREAD|CRTSCTS); //Control options
 options.c_cflag&=~CSIZE; //Control options
 options.c_lflag=ICANON; //Local options
 //options.c_oflag&=~OPOST; //Output options
 options.c_oflag=0; //Output options,Raw模式
 options.c_iflag=(IGNPAR|ICRNL); //Input options
 options.c_cc[VTIME]=0;
 options.c_cc[VMIN]=1;
 options.c_cc[VEOF]=4;
// options.c_iflag&=~(IXON|IXOFF|IXANY); //Input options
 /*以下为Control characters
  options.c_cc[VINTR]=0;//Ctrl-c
 options.c_cc[VQUIT]=0;//Ctrl-
 options.c_cc[VERASE]=0;//del
 options.c_cc[VKILL]=0;//@
 options.c_cc[VEOF]=4;//Ctrl-d
 options.c_cc[VTIME]=0;//不使用分割字元组的计时器
 options.c_cc[VMIN]=1;//在读取到 1 个字元前先停止
 options.c_cc[VSWTC]=0;//'\0'
 options.c_cc[VSTART]=0; //Ctrl-q
 options.c_cc[VSTOP]=0; //Ctrl-s
 options.c_cc[VSUSP]=26; //Ctrl-z
 options.c_cc[VEOL]=0; //'\0'
 options.c_cc[VREPRINT]=0; //Ctrl-r
 options.c_cc[VDISCARD]=0; //Ctrl-u
 options.c_cc[VWERASE]=0; //Ctrl-w
 options.c_cc[VLNEXT]=0; //Ctrl-v
 options.c_cc[VEOL2]=0; //'\0'*/
 //设置波特率
 for(i=0;i {
  if(BaudRate==speed_name[i])
  {
   options.c_cflag|=speed_value[i];
   break;
  }
 }
 //设置校验位
 switch(ParityBits)
 {
  case 'o':case 'O': //奇校验
   options.c_cflag|=(PARODD|PARENB);
   options.c_iflag|=INPCK;
   break;
  case 'e':case 'E': //偶校验
   options.c_cflag|=PARENB;
   options.c_cflag&=~PARODD;
   options.c_iflag|=INPCK;
   break;
  case 's':case 'S': //Space校验
   options.c_cflag&=~PARENB;
   options.c_cflag&=~CSTOPB;
   options.c_iflag|=INPCK;
   break;
  default: //默认为无校验,即'n'或'N'
   options.c_cflag&=~PARENB;
   options.c_iflag&=~INPCK;
 }
 //设置数据位
 if(DataBits==7)
  options.c_cflag|=CS7;
 else
  options.c_cflag|=CS8;
 //设置停止位
 if(StopBits==1)
  options.c_cflag&=~CSTOPB;
 else
  options.c_cflag|=CSTOPB;
 //清空数据线,并启用新的设置
 tcflush(hComm,TCIFLUSH);
 tcsetattr(hComm,TCSANOW,&options);
}
int WriteComm(int hComm,char *pBuff) //写串口
{
 int iBytes=0;
 iBytes=write(hComm,pBuff,strlen(pBuff));
 return(iBytes);
}
unsigned char *ReadComm(int hComm) //以同步方式读串口
{
 int iBytes;
 static unsigned char szBuff[256]; //数据缓存
 memset(szBuff,0,256);
 iBytes=read(hComm,szBuff,256);
 return(szBuff);
}
#endif

 
    五、sms.h,基于短信猫的短信收发函数库:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:sms.h 
    功能说明:SMS短信收发函数库 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#ifndef SMS_INFO_DEF  
#define SMS_INFO_DEF  
 
#include "stringex.h" //必须包含此头文件  
#include "synccom.h" //必需包含此头文件  
 
//BYTE SSTR_SMS_CODE,SSTR_AREA_CODE; //短信中心号码,小灵通区号  
struct SMS_INFO  
{  
    int hComm; //短信设备句柄  
    int iDelayTime; //等待延时  
    BYTE SMS_CODE[16]; //短信中心号码  
    BYTE SMS_CODE_PDU[16];//PDU编码的短信中心号码,需要调用者转换  
    BYTE SMS_CODE_TYPE; //短信中心号码类型,0:移动,1:联通,2:小灵通  
    BYTE AREA_CODE[4]; //小灵通区号,由于要在TEL2PDU辅助函数中用,需要调用者赋值  
};  
 
struct SMS_INFO *OpenModem(int iCommPort,int iBaudRate,int iRetry); //初始化短信猫设备  
void CloseModem(struct SMS_INFO *pSms); //关闭短信猫设备  
int SendMessage(struct SMS_INFO *pSms,LPBYTE pUserCode,LPBYTE pMessage); //发送短信,pUserCode:接收手机号码,pMessage:短信内容,可递归调用  
 
int WriteModem(int hComm,char *pMessage,int iRetry); //辅助函数,向短信猫写数据  
int ReadModem(int hComm,int iRetry); //辅助函数,读短信猫的反馈信息,-1:错误,0:超时,1:正确  
void TEL2PDU(LPBYTE pSrcCode,LPBYTE pDstCode,LPBYTE pAreaCode); //辅助函数,电话号码转PDU编码字符串  
void PDU2TEL(LPBYTE pSrcCode,LPBYTE pDstCode); //辅助函数,PDU编码字符串转电话号码  
 
struct SMS_INFO *OpenModem(int iCommPort,int iBaudRate,int iRetry) //初始化短信猫设备,iCommPort:串口号,iRetry:重试次数  
{  
    int i;  
    static struct SMS_INFO m_Sms;  
 
    m_Sms.hComm=OpenComm(iCommPort); //打开短信猫所连的串口  
    if(m_Sms.hComm<1)return(NULL);  
 
    SetCommParam(m_Sms.hComm,iBaudRate,'N',8,1); //设置串口通讯参数  
 
    m_Sms.SMS_CODE[0]='\0';  
    m_Sms.AREA_CODE[0]='\0';  
    m_Sms.SMS_CODE_TYPE='0';  
    m_Sms.iDelayTime=0;  
    m_Sms.SMS_CODE_PDU[0]='\0';  
 
    //初始化短信猫设备  
    for(i=0;i    {  
        WriteComm(m_Sms.hComm,"AT\r");  
        if((ReadModem(m_Sms.hComm,10))==1)  
        {  
            WriteComm(m_Sms.hComm,"ATE0\r");  
            if((ReadModem(m_Sms.hComm,10))==1) //成功初始化  
            {  
                //设置是否接收短信通知  
                WriteComm(m_Sms.hComm,"AT+CNMI=0,0,0,0,1\r");  
                if((ReadModem(m_Sms.hComm,10))==1) //0,0,0,0,1(不通知),1,1,0,2,1(通知)  
                {  
                    printf("短信猫初始化成功!\n");  
                    return(&m_Sms);  
                }  
            }  
        }  
        printf("第%d次初始化短信猫失败!\n",i+1);  
    }  
    CloseComm(m_Sms.hComm); //当指定的次数内不能完成初始化时,关闭串口  
    return(NULL);  
}  
 
void CloseModem(struct SMS_INFO *pSms)  
{  
    if(pSms!=NULL)  
        CloseComm(pSms->hComm);  
}  
 
int SendMessage(struct SMS_INFO *pSms,LPBYTE pUserCode,LPBYTE pMessage) //发送短信,pUserCode:接收手机号码,pMessage:短信内容,可递归调用  
/*数据包结构说明: 
    1-2位:(短信中心号码长度+2(即3-4位长度))/2(16进制) 
    3-4位:短信中心号码有无国家编码(91有,81无) 
    X位:短信中心号码(需PDU编码),以下为X位后 
    1-2位:状态报告(31有,11无) *注意:从此处开始计算数据包长度 
    3-4位:分隔符(永远为00) 
    5-6位:目标号码长度(16进制) 
    7-8位:目标号码有无国家编码(91有,81无) 
    XX为:目标号码(需PDU编码),以下为XX位后 
    1-2位:TP-PID协议(一般为00) 
    3-4为:是否免提(18是,08否) 
    5-6位:有效期标志(一般为00) 
    7-8位:短信实际长度(16进制) 
    XXX位:短信内容,以下为XXX位后 
    1位:结束符(ASCII码26) 
*/ 
{  
    static unsigned char bIsHex=0; //HEX编码标志,0:未经过编码,1:已编码  
    int iRetval=0; //返回值,0表示失败,1表示成功  
    int iPacketLen; //数据包长度,从第19个字符开始计算(需除2)  
    int iTextLen=strlen(pMessage); //实际短信内容长度(需除2)  
    BYTE szBuff[64]; //临时变量  
    BYTE szText[300]; //短信内容,,一条短信最多70个字符(即140个HEX字符)  
    BYTE szTextHEX[1024]; //经过HEX编码的短信内容  
    BYTE szPacket[512]; //短信数据包  
    BYTE szUserCodePDU[20]; //经过PDU编码的接收手机号码  
 
    if(iTextLen==0) //如果pMessage长度为0,则直接返回  
    {  
        bIsHex=0; //重置HEX编码标志  
        return(0); //如果待发短信内容的长度为0,则直接返回  
    }  
 
    if(bIsHex==0) //如果参数pMessage没有经过HEX编码,则进行HEX编码  
    {  
        bIsHex=1; //置标志为已编码状态  
        str2hex(szTextHEX,pMessage); //将pMessage进行HEX编码,并放入szTextHEX变量  
        TEL2PDU(pUserCode,szUserCodePDU,pSms->AREA_CODE); //将接收手机号进行PDU编码  
        iTextLen=strlen(szTextHEX);  
    }else //否则  
    {  
        strcpy(szTextHEX,pMessage);  
        strcpy(szUserCodePDU,pUserCode);  
    }  
 
    //取前70个字符(即280个HEX编码字符)  
    iTextLen=(iTextLen>280)?280:iTextLen;  
    strncpy(szText,szTextHEX,iTextLen);  
    szText[iTextLen]='\0';  
    memset(szPacket,0,512); //清空数据包缓冲区  
 
    /* **********************************封装数据包***************************** */ 
    iTextLen=(strlen(pSms->SMS_CODE_PDU)+2)/2; //数据包的第一个长度字段,即(中心号码长度+2位国家编码长度)/2  
    sprintf(szPacket,(iTextLen>15)?"%2X":"0%1X",iTextLen);  
    sprintf(szPacket,"%s%d",szPacket,((pSms->SMS_CODE_PDU[0]=='6')&&(pSms->SMS_CODE_PDU[1]=='8'))?91:81); //中心号码有无国家编码  
    sprintf(szPacket,"%s%s",szPacket,pSms->SMS_CODE_PDU); //中心号码  
    iPacketLen=strlen(szPacket); //从此处开始计算数据包长度(即短信中心号码以后的字符串长度的1/2)  
    sprintf(szPacket,"%s3100",szPacket); //状态报告、分隔符  
    iTextLen=strlen(szUserCodePDU)-1; //去掉最后一个'F'  
    sprintf(szPacket,(iTextLen>15)?"%s%2X":"%s0%1X",szPacket,iTextLen); //目标号码长度  
    sprintf(szPacket,"%s%d",szPacket,((szUserCodePDU[0]=='6')&&(szUserCodePDU[1]=='8'))?91:81); //目标号码有无国家编码  
    sprintf(szPacket,"%s%s",szPacket,szUserCodePDU); //目标号码  
    sprintf(szPacket,"%s000800",szPacket); //TP-PID协议、免提标志、有效期  
    iTextLen=strlen(szText)/2; //短信内容实际长度  
    sprintf(szPacket,(iTextLen>15)?"%s%2X":"%s0%1X",szPacket,iTextLen);  
    sprintf(szPacket,"%s%s%c",szPacket,szText,26); //短信内容及结束符(结束符为1A1D,也有为ASCII码26的)  
    /* ***********************************封装结束****************************** */ 
 
    //计算数据包长度  
    iPacketLen=strlen(szPacket+iPacketLen)/2;  
 
    //向GSM MODEM发送控制符,通知以PDU模式发送短信  
    if((WriteModem(pSms->hComm,"AT+CMGF=0\r",3))==1)  
    {  
        //发送数据包长度(尝试5次)  
        sprintf(szBuff,"AT+CMGS=%d\r",iPacketLen);  
        WriteComm(pSms->hComm,szBuff);  
        if((ReadModem(pSms->hComm,50))==1)  
        {  
            usleep(100000);  
            WriteComm(pSms->hComm,szPacket); //发送短信数据包  
            iRetval=(ReadModem(pSms->hComm,80));  
        }  
    }  
 
    //根据短信中心号码类型进行延时,以等待短信发送成功  
    sleep(pSms->iDelayTime);  
 
    //如果还有未发的短信内容,则进入递归调用  
    if(strlen(szTextHEX)>280)  
        SendMessage(pSms,szUserCodePDU,(LPBYTE)(szTextHEX+280));  
 
    bIsHex=0; //重置标志  
    return(iRetval);  
}  
 
int WriteModem(int hComm,char *pMessage,int iRetry) //辅助函数,向短信猫写数据  
{  
    int i,res;  
    for(i=0;i    {  
        WriteComm(hComm,pMessage);  
        res=ReadModem(hComm,10);  
        if(res==1)  
            return(1);  
              
    }  
    return(0);  
}  
 
int ReadModem(int hComm,int iRetry) //辅助函数,度短信猫的反馈信息,-1:错误,0:超时,1:正确  
{  
    int i;  
    char *p;  
    for(i=0;i    {  
        usleep(50000); //延时50毫秒  
        p=ReadComm(hComm);  
 
        if((strcmp(p,"OK")>=0)||(strcmp(p,">")>=0))  
            return(1);  
        else if(strcmp(p,"ERROR")>=0)  
            return(-1);  
    }  
    return(0);  
}  
 
void TEL2PDU(LPBYTE pSrcCode,LPBYTE pDstCode,LPBYTE pAreaCode) //辅助函数,电话号码转PDU字符串  
{  
    int i,l;  
    BYTE szBuff[16];//临时变量  
 
    //根据是否有区号判断号码是否为小灵通  
    if(pSrcCode[0]=='0') //如果是,则加上106前缀  
        sprintf(szBuff,"106%s",pSrcCode);   
    else 
    {  
        //根据长度是否小于11位判断是否为小灵通  
        l=strlen(pSrcCode);  
        if(l<11) //如果长度小于11位,则为未加区号的小灵通  
            sprintf(szBuff,"106%s%s",pAreaCode,pSrcCode);  
        else //否则为手机号码  
        {  
            if((pSrcCode[0]!='8')||(pSrcCode[1]!='6'))  
                sprintf(szBuff,"86%s",pSrcCode);  
            else 
                strcpy(szBuff,pSrcCode);  
        }  
    }  
    //判断加上前缀后的号码长度是否为奇数,如果是,则在最后补"F"字符  
    l=strlen(szBuff)+1;  
    if((l % 2)==0)  
        sprintf(szBuff,"%sF",szBuff);  
    //对号码进行PDU编码,即奇偶对调  
    for(i=0;i    {  
        pDstCode[i]=szBuff[i+1];  
        pDstCode[i+1]=szBuff[i];  
    }  
    pDstCode[l]='\0';  
}  
 
void PDU2TEL(LPBYTE pSrcCode,LPBYTE pDstCode) //辅助函数,PDU字符串转电话号码  
{  
    int i;  
    BYTE szBuff[16]; //临时变量  
 
    memset(szBuff,0,16);  
    //奇偶对调  
    for(i=0;i    {  
        szBuff[i]=pSrcCode[i+1];  
        szBuff[i+1]=pSrcCode[i];  
    }  
 
    //截去后缀字符F(如果有)  
    i=strlen(szBuff);  
    if(szBuff[i-1]=='F')szBuff[i-1]='\0';  
 
    strcpy(pDstCode,szBuff);  
}  
 
#endif 
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:sms.h
 功能说明:SMS短信收发函数库
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#ifndef SMS_INFO_DEF
#define SMS_INFO_DEF
#include "stringex.h" //必须包含此头文件
#include "synccom.h" //必需包含此头文件
//BYTE SSTR_SMS_CODE,SSTR_AREA_CODE; //短信中心号码,小灵通区号
struct SMS_INFO
{
 int hComm; //短信设备句柄
 int iDelayTime; //等待延时
 BYTE SMS_CODE[16]; //短信中心号码
 BYTE SMS_CODE_PDU[16];//PDU编码的短信中心号码,需要调用者转换
 BYTE SMS_CODE_TYPE; //短信中心号码类型,0:移动,1:联通,2:小灵通
 BYTE AREA_CODE[4]; //小灵通区号,由于要在TEL2PDU辅助函数中用,需要调用者赋值
};
struct SMS_INFO *OpenModem(int iCommPort,int iBaudRate,int iRetry); //初始化短信猫设备
void CloseModem(struct SMS_INFO *pSms); //关闭短信猫设备
int SendMessage(struct SMS_INFO *pSms,LPBYTE pUserCode,LPBYTE pMessage); //发送短信,pUserCode:接收手机号码,pMessage:短信内容,可递归调用
int WriteModem(int hComm,char *pMessage,int iRetry); //辅助函数,向短信猫写数据
int ReadModem(int hComm,int iRetry); //辅助函数,读短信猫的反馈信息,-1:错误,0:超时,1:正确
void TEL2PDU(LPBYTE pSrcCode,LPBYTE pDstCode,LPBYTE pAreaCode); //辅助函数,电话号码转PDU编码字符串
void PDU2TEL(LPBYTE pSrcCode,LPBYTE pDstCode); //辅助函数,PDU编码字符串转电话号码
struct SMS_INFO *OpenModem(int iCommPort,int iBaudRate,int iRetry) //初始化短信猫设备,iCommPort:串口号,iRetry:重试次数
{
 int i;
 static struct SMS_INFO m_Sms;
 m_Sms.hComm=OpenComm(iCommPort); //打开短信猫所连的串口
 if(m_Sms.hComm<1)return(NULL);
 SetCommParam(m_Sms.hComm,iBaudRate,'N',8,1); //设置串口通讯参数
 m_Sms.SMS_CODE[0]='\0';
 m_Sms.AREA_CODE[0]='\0';
 m_Sms.SMS_CODE_TYPE='0';
 m_Sms.iDelayTime=0;
 m_Sms.SMS_CODE_PDU[0]='\0';
 //初始化短信猫设备
 for(i=0;i {
  WriteComm(m_Sms.hComm,"AT\r");
  if((ReadModem(m_Sms.hComm,10))==1)
  {
   WriteComm(m_Sms.hComm,"ATE0\r");
   if((ReadModem(m_Sms.hComm,10))==1) //成功初始化
   {
    //设置是否接收短信通知
    WriteComm(m_Sms.hComm,"AT+CNMI=0,0,0,0,1\r");
    if((ReadModem(m_Sms.hComm,10))==1) //0,0,0,0,1(不通知),1,1,0,2,1(通知)
    {
     printf("短信猫初始化成功!\n");
     return(&m_Sms);
    }
   }
  }
  printf("第%d次初始化短信猫失败!\n",i+1);
 }
 CloseComm(m_Sms.hComm); //当指定的次数内不能完成初始化时,关闭串口
 return(NULL);
}
void CloseModem(struct SMS_INFO *pSms)
{
 if(pSms!=NULL)
  CloseComm(pSms->hComm);
}
int SendMessage(struct SMS_INFO *pSms,LPBYTE pUserCode,LPBYTE pMessage) //发送短信,pUserCode:接收手机号码,pMessage:短信内容,可递归调用
/*数据包结构说明:
 1-2位:(短信中心号码长度+2(即3-4位长度))/2(16进制)
 3-4位:短信中心号码有无国家编码(91有,81无)
 X位:短信中心号码(需PDU编码),以下为X位后
 1-2位:状态报告(31有,11无) *注意:从此处开始计算数据包长度
 3-4位:分隔符(永远为00)
 5-6位:目标号码长度(16进制)
 7-8位:目标号码有无国家编码(91有,81无)
 XX为:目标号码(需PDU编码),以下为XX位后
 1-2位:TP-PID协议(一般为00)
 3-4为:是否免提(18是,08否)
 5-6位:有效期标志(一般为00)
 7-8位:短信实际长度(16进制)
 XXX位:短信内容,以下为XXX位后
 1位:结束符(ASCII码26)
*/
{
 static unsigned char bIsHex=0; //HEX编码标志,0:未经过编码,1:已编码
 int iRetval=0; //返回值,0表示失败,1表示成功
 int iPacketLen; //数据包长度,从第19个字符开始计算(需除2)
 int iTextLen=strlen(pMessage); //实际短信内容长度(需除2)
 BYTE szBuff[64]; //临时变量
 BYTE szText[300]; //短信内容,,一条短信最多70个字符(即140个HEX字符)
 BYTE szTextHEX[1024]; //经过HEX编码的短信内容
 BYTE szPacket[512]; //短信数据包
 BYTE szUserCodePDU[20]; //经过PDU编码的接收手机号码
 if(iTextLen==0) //如果pMessage长度为0,则直接返回
 {
  bIsHex=0; //重置HEX编码标志
  return(0); //如果待发短信内容的长度为0,则直接返回
 }
 if(bIsHex==0) //如果参数pMessage没有经过HEX编码,则进行HEX编码
 {
  bIsHex=1; //置标志为已编码状态
  str2hex(szTextHEX,pMessage); //将pMessage进行HEX编码,并放入szTextHEX变量
  TEL2PDU(pUserCode,szUserCodePDU,pSms->AREA_CODE); //将接收手机号进行PDU编码
  iTextLen=strlen(szTextHEX);
 }else //否则
 {
  strcpy(szTextHEX,pMessage);
  strcpy(szUserCodePDU,pUserCode);
 }
 //取前70个字符(即280个HEX编码字符)
 iTextLen=(iTextLen>280)?280:iTextLen;
 strncpy(szText,szTextHEX,iTextLen);
 szText[iTextLen]='\0';
 memset(szPacket,0,512); //清空数据包缓冲区
 /* **********************************封装数据包***************************** */
 iTextLen=(strlen(pSms->SMS_CODE_PDU)+2)/2; //数据包的第一个长度字段,即(中心号码长度+2位国家编码长度)/2
 sprintf(szPacket,(iTextLen>15)?"%2X":"0%1X",iTextLen);
 sprintf(szPacket,"%s%d",szPacket,((pSms->SMS_CODE_PDU[0]=='6')&&(pSms->SMS_CODE_PDU[1]=='8'))?91:81); //中心号码有无国家编码
 sprintf(szPacket,"%s%s",szPacket,pSms->SMS_CODE_PDU); //中心号码
 iPacketLen=strlen(szPacket); //从此处开始计算数据包长度(即短信中心号码以后的字符串长度的1/2)
 sprintf(szPacket,"%s3100",szPacket); //状态报告、分隔符
 iTextLen=strlen(szUserCodePDU)-1; //去掉最后一个'F'
 sprintf(szPacket,(iTextLen>15)?"%s%2X":"%s0%1X",szPacket,iTextLen); //目标号码长度
 sprintf(szPacket,"%s%d",szPacket,((szUserCodePDU[0]=='6')&&(szUserCodePDU[1]=='8'))?91:81); //目标号码有无国家编码
 sprintf(szPacket,"%s%s",szPacket,szUserCodePDU); //目标号码
 sprintf(szPacket,"%s000800",szPacket); //TP-PID协议、免提标志、有效期
 iTextLen=strlen(szText)/2; //短信内容实际长度
 sprintf(szPacket,(iTextLen>15)?"%s%2X":"%s0%1X",szPacket,iTextLen);
 sprintf(szPacket,"%s%s%c",szPacket,szText,26); //短信内容及结束符(结束符为1A1D,也有为ASCII码26的)
 /* ***********************************封装结束****************************** */
 //计算数据包长度
 iPacketLen=strlen(szPacket+iPacketLen)/2;
 //向GSM MODEM发送控制符,通知以PDU模式发送短信
 if((WriteModem(pSms->hComm,"AT+CMGF=0\r",3))==1)
 {
  //发送数据包长度(尝试5次)
  sprintf(szBuff,"AT+CMGS=%d\r",iPacketLen);
  WriteComm(pSms->hComm,szBuff);
  if((ReadModem(pSms->hComm,50))==1)
  {
   usleep(100000);
   WriteComm(pSms->hComm,szPacket); //发送短信数据包
   iRetval=(ReadModem(pSms->hComm,80));
  }
 }
 //根据短信中心号码类型进行延时,以等待短信发送成功
 sleep(pSms->iDelayTime);
 //如果还有未发的短信内容,则进入递归调用
 if(strlen(szTextHEX)>280)
  SendMessage(pSms,szUserCodePDU,(LPBYTE)(szTextHEX+280));
 bIsHex=0; //重置标志
 return(iRetval);
}
int WriteModem(int hComm,char *pMessage,int iRetry) //辅助函数,向短信猫写数据
{
 int i,res;
 for(i=0;i {
  WriteComm(hComm,pMessage);
  res=ReadModem(hComm,10);
  if(res==1)
   return(1);
   
 }
 return(0);
}
int ReadModem(int hComm,int iRetry) //辅助函数,度短信猫的反馈信息,-1:错误,0:超时,1:正确
{
 int i;
 char *p;
 for(i=0;i {
  usleep(50000); //延时50毫秒
  p=ReadComm(hComm);
  if((strcmp(p,"OK")>=0)||(strcmp(p,">")>=0))
   return(1);
  else if(strcmp(p,"ERROR")>=0)
   return(-1);
 }
 return(0);
}
void TEL2PDU(LPBYTE pSrcCode,LPBYTE pDstCode,LPBYTE pAreaCode) //辅助函数,电话号码转PDU字符串
{
 int i,l;
 BYTE szBuff[16];//临时变量
 //根据是否有区号判断号码是否为小灵通
 if(pSrcCode[0]=='0') //如果是,则加上106前缀
  sprintf(szBuff,"106%s",pSrcCode);
 else
 {
  //根据长度是否小于11位判断是否为小灵通
  l=strlen(pSrcCode);
  if(l<11) //如果长度小于11位,则为未加区号的小灵通
   sprintf(szBuff,"106%s%s",pAreaCode,pSrcCode);
  else //否则为手机号码
  {
   if((pSrcCode[0]!='8')||(pSrcCode[1]!='6'))
    sprintf(szBuff,"86%s",pSrcCode);
   else
    strcpy(szBuff,pSrcCode);
  }
 }
 //判断加上前缀后的号码长度是否为奇数,如果是,则在最后补"F"字符
 l=strlen(szBuff)+1;
 if((l % 2)==0)
  sprintf(szBuff,"%sF",szBuff);
 //对号码进行PDU编码,即奇偶对调
 for(i=0;i {
  pDstCode[i]=szBuff[i+1];
  pDstCode[i+1]=szBuff[i];
 }
 pDstCode[l]='\0';
}
void PDU2TEL(LPBYTE pSrcCode,LPBYTE pDstCode) //辅助函数,PDU字符串转电话号码
{
 int i;
 BYTE szBuff[16]; //临时变量
 memset(szBuff,0,16);
 //奇偶对调
 for(i=0;i {
  szBuff[i]=pSrcCode[i+1];
  szBuff[i+1]=pSrcCode[i];
 }
 //截去后缀字符F(如果有)
 i=strlen(szBuff);
 if(szBuff[i-1]=='F')szBuff[i-1]='\0';
 strcpy(pDstCode,szBuff);
}
#endif
 
     六、gsmd.c,短信收发主程序:
view plaincopy to clipboardprint?
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
    文件名称:gsmd.c 
    功能说明:短信发送程序入口 
    编者信息:lyserver 
    联系方式:http://blog.csdn.net/lyserver 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ 
#include "daemon.h"  
#include "sms.h"  
#include "inifile.h"  
#include "stringex.h"  
#include "/usr/include/mysql/mysql.h"  
 
/*全局变量*/ 
struct SMS_INFO *hModem; //短信猫设备变量  
 
char szServer[32]; //数据库服务器名称  
char szDatabase[24]; //数据库名称  
char szUserName[12]; //数据库用户名  
char szPassword[12]; //数据库密码  
 
long lRunTime; //事件发生次数  
int iIntervalTime; //事件间隔时间  
 
int MessageLoop(FILE *hLog); //函数声明,主程序代码片段  
 
int main(int argc,char *argv[]) //程序入口  
{  
    FILE *hLog;  
    int iCommPort=1,iBaudRate=19200; //串口设置变量,iCommPort:串口号,iBaudRate:波特率,iDelayTime:延时  
    int iDelayTime=4;  
 
    char szAreaCode[5],szSmsCode[16],chSmsType; //短信号码设置变量,szAreaCode:小灵通区号,szSmsCode:短信中心号码,chSmsType:短信中心号码类型  
      
    struct FILE_INFO *hFile; //配置文件变量  
 
    //读取参数配置文件  
    hFile=OpenIniFile("gsmd.conf");  
    if(hFile==NULL)return(1);  
 
    strcpy(szSmsCode,GetKeyValue(hFile,"MOBILE_CODE","SMS_CODE"));  
    chSmsType=GetKeyValue(hFile,"MOBILE_CODE","SMS_CODE")[0];  
    strcpy(szAreaCode,GetKeyValue(hFile,"MOBILE_CODE","AREA_CODE"));  
    iCommPort=atol(GetKeyValue(hFile,"COMM_SETTING","COMM_PORT"));  
    iBaudRate=atol(GetKeyValue(hFile,"COMM_SETTING","BAUD_RATE"));  
    strcpy(szServer,GetKeyValue(hFile,"DATABASE","SERVER"));  
    strcpy(szDatabase,GetKeyValue(hFile,"DATABASE","DATABASE"));  
    strcpy(szUserName,GetKeyValue(hFile,"DATABASE","USERNAME"));  
    strcpy(szPassword,GetKeyValue(hFile,"DATABASE","PASSWORD"));  
    lRunTime=atol(GetKeyValue(hFile,"EVENT","RUN_TIME"));  
    iDelayTime=atol(GetKeyValue(hFile,"EVENT","DELAY_TIME"));  
    iIntervalTime=atol(GetKeyValue(hFile,"EVENT","INTERVAL_TIME"));  
 
    //关闭配置文件  
    CloseIniFile(hFile);  
 
    //打开短信猫设备  
    hModem=OpenModem(iCommPort,iBaudRate,1000);  
    if(hModem==NULL)return(2);  
 
    printf("SMS短信服务程序已成功启动......\n");  
 
    //对短信猫设备变量进行一些设置  
    strncpy(hModem->AREA_CODE,szAreaCode,4); //设置区号  
    hModem->AREA_CODE[4]='\0';  
    strcpy(hModem->SMS_CODE,szSmsCode);  
    hModem->SMS_CODE_TYPE=chSmsType;  
    hModem->iDelayTime=iDelayTime;  
    TEL2PDU(hModem->SMS_CODE,hModem->SMS_CODE_PDU,hModem->AREA_CODE); //对短信中心号码进行PDU编码  
 
    //将程序转为后台运行  
    //MakeDaemon("gsmd.log",&MessageLoop);  
 
    MessageLoop(NULL);  
    //关闭短信猫  
    CloseModem(hModem);  
 
    printf("SMS短信服务程序已停止运行!\n");  
 
    return(0);  
}  
 
int MessageLoop(FILE *hLog) //函数声明,主程序代码片段  
{  
    long lEvent=0;  
    int col_num,row_num;  
    MYSQL my_cn;  
    MYSQL_RES *res_ptr;  
    MYSQL_ROW my_row;  
    char szSQL[256];  
 
    //打开数据库  
    mysql_init(&my_cn);  
    if(mysql_real_connect(&my_cn,szServer,szUserName,szPassword,szDatabase,0,NULL,CLIENT_FOUND_ROWS)==NULL)  
        return(-1);  
    //循环查询是否有等待发送的短信  
    while(1)  
    {  
        strcpy(szSQL,"select DEST_TERMINAL_ID,MSG_CONTENT,ROW_ID from submit_msg_base ");  
        strcat(szSQL,"where instr('130131132133134155156135',left(DEST_TERMINAL_ID,3))>0 ");  
        strcat(szSQL,"and (ROW_ID Not In (select ROW_ID from submit_msg_status_sending))");  
 
        if(mysql_query(&my_cn,szSQL)) //如果有查询结果  
        {  
            res_ptr=mysql_store_result(&my_cn);  
            if(res_ptr)  
            {  
                row_num=mysql_num_rows(res_ptr);  
                col_num=mysql_num_fields(res_ptr);  
                if(row_num>0)  
                {  
                    while((my_row=mysql_fetch_row(res_ptr)))  
                    {  
                        //将未发短信放入正在发送的表中  
                        sprintf(szSQL,"insert into submit_msg_status_sending(ROW_ID) values(%s)",my_row[2]);  
                        mysql_query(&my_cn,szSQL);  
 
                        //发送短信  
                        if((SendMessage(hModem,my_row[0],my_row[1]))==1) //发送成功  
                        {  
                            //写日志  
                            if(hLog!=NULL){  
                            sprintf(szSQL,"ROW_ID为%d的短信于%d成功发送。\n",my_row[2],GetCurrentDateAndTime());  
                            fputs(szSQL,hLog);  
                            fflush(hLog);}  
                            //将已发短信放入已发送的表中  
                            sprintf(szSQL,"insert into submit_msg_status_sended(ROW_ID) values(%s)",my_row[2]);  
                            mysql_query(&my_cn,szSQL);  
                        }  
                    }  
                }  
            }  
            mysql_free_result(res_ptr);  
        }  
        if(lEvent<10000000)  
            lEvent++;  
        if((lEvent>lRunTime)&&(lRunTime!=-1))  
            break;  
        //延时  
        sleep(iIntervalTime);  
    }  
    mysql_close(&my_cn);  
    return(0);  

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 文件名称:gsmd.c
 功能说明:短信发送程序入口
 编者信息:lyserver
 联系方式:http://blog.csdn.net/lyserver
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
#include "daemon.h"
#include "sms.h"
#include "inifile.h"
#include "stringex.h"
#include "/usr/include/mysql/mysql.h"
/*全局变量*/
struct SMS_INFO *hModem; //短信猫设备变量
char szServer[32]; //数据库服务器名称
char szDatabase[24]; //数据库名称
char szUserName[12]; //数据库用户名
char szPassword[12]; //数据库密码
long lRunTime; //事件发生次数
int iIntervalTime; //事件间隔时间
int MessageLoop(FILE *hLog); //函数声明,主程序代码片段
int main(int argc,char *argv[]) //程序入口
{
 FILE *hLog;
 int iCommPort=1,iBaudRate=19200; //串口设置变量,iCommPort:串口号,iBaudRate:波特率,iDelayTime:延时
 int iDelayTime=4;
 char szAreaCode[5],szSmsCode[16],chSmsType; //短信号码设置变量,szAreaCode:小灵通区号,szSmsCode:短信中心号码,chSmsType:短信中心号码类型
 
 struct FILE_INFO *hFile; //配置文件变量
 //读取参数配置文件
 hFile=OpenIniFile("gsmd.conf");
 if(hFile==NULL)return(1);
 strcpy(szSmsCode,GetKeyValue(hFile,"MOBILE_CODE","SMS_CODE"));
 chSmsType=GetKeyValue(hFile,"MOBILE_CODE","SMS_CODE")[0];
 strcpy(szAreaCode,GetKeyValue(hFile,"MOBILE_CODE","AREA_CODE"));
 iCommPort=atol(GetKeyValue(hFile,"COMM_SETTING","COMM_PORT"));
 iBaudRate=atol(GetKeyValue(hFile,"COMM_SETTING","BAUD_RATE"));
 strcpy(szServer,GetKeyValue(hFile,"DATABASE","SERVER"));
 strcpy(szDatabase,GetKeyValue(hFile,"DATABASE","DATABASE"));
 strcpy(szUserName,GetKeyValue(hFile,"DATABASE","USERNAME"));
 strcpy(szPassword,GetKeyValue(hFile,"DATABASE","PASSWORD"));
 lRunTime=atol(GetKeyValue(hFile,"EVENT","RUN_TIME"));
 iDelayTime=atol(GetKeyValue(hFile,"EVENT","DELAY_TIME"));
 iIntervalTime=atol(GetKeyValue(hFile,"EVENT","INTERVAL_TIME"));
 //关闭配置文件
 CloseIniFile(hFile);
 //打开短信猫设备
 hModem=OpenModem(iCommPort,iBaudRate,1000);
 if(hModem==NULL)return(2);
 printf("SMS短信服务程序已成功启动......\n");
 //对短信猫设备变量进行一些设置
 strncpy(hModem->AREA_CODE,szAreaCode,4); //设置区号
 hModem->AREA_CODE[4]='\0';
 strcpy(hModem->SMS_CODE,szSmsCode);
 hModem->SMS_CODE_TYPE=chSmsType;
 hModem->iDelayTime=iDelayTime;
 TEL2PDU(hModem->SMS_CODE,hModem->SMS_CODE_PDU,hModem->AREA_CODE); //对短信中心号码进行PDU编码
 //将程序转为后台运行
 //MakeDaemon("gsmd.log",&MessageLoop);
 MessageLoop(NULL);
 //关闭短信猫
 CloseModem(hModem);
 printf("SMS短信服务程序已停止运行!\n");
 return(0);
}
int MessageLoop(FILE *hLog) //函数声明,主程序代码片段
{
 long lEvent=0;
 int col_num,row_num;
 MYSQL my_cn;
 MYSQL_RES *res_ptr;
 MYSQL_ROW my_row;
 char szSQL[256];
 //打开数据库
 mysql_init(&my_cn);
 if(mysql_real_connect(&my_cn,szServer,szUserName,szPassword,szDatabase,0,NULL,CLIENT_FOUND_ROWS)==NULL)
  return(-1);
 //循环查询是否有等待发送的短信
 while(1)
 {
  strcpy(szSQL,"select DEST_TERMINAL_ID,MSG_CONTENT,ROW_ID from submit_msg_base ");
  strcat(szSQL,"where instr('130131132133134155156135',left(DEST_TERMINAL_ID,3))>0 ");
  strcat(szSQL,"and (ROW_ID Not In (select ROW_ID from submit_msg_status_sending))");
  if(mysql_query(&my_cn,szSQL)) //如果有查询结果
  {
   res_ptr=mysql_store_result(&my_cn);
   if(res_ptr)
   {
    row_num=mysql_num_rows(res_ptr);
    col_num=mysql_num_fields(res_ptr);
    if(row_num>0)
    {
     while((my_row=mysql_fetch_row(res_ptr)))
     {
      //将未发短信放入正在发送的表中
      sprintf(szSQL,"insert into submit_msg_status_sending(ROW_ID) values(%s)",my_row[2]);
      mysql_query(&my_cn,szSQL);
      //发送短信
      if((SendMessage(hModem,my_row[0],my_row[1]))==1) //发送成功
      {
       //写日志
       if(hLog!=NULL){
       sprintf(szSQL,"ROW_ID为%d的短信于%d成功发送。\n",my_row[2],GetCurrentDateAndTime());
       fputs(szSQL,hLog);
       fflush(hLog);}
       //将已发短信放入已发送的表中
       sprintf(szSQL,"insert into submit_msg_status_sended(ROW_ID) values(%s)",my_row[2]);
       mysql_query(&my_cn,szSQL);
      }
     }
    }
   }
   mysql_free_result(res_ptr);
  }
  if(lEvent<10000000)
   lEvent++;
  if((lEvent>lRunTime)&&(lRunTime!=-1))
   break;
  //延时
  sleep(iIntervalTime);
 }
 mysql_close(&my_cn);
 return(0);
}
 
     七、本程序在red linux下使用cc编译器进行编译,make.txt文件如下:
    cc gsmd.c -o gsmd -I /usr/include/mysql -L /usr/lib/mysql -l mysqlclient -lz
    至此,一个完整的短信收发程序已成功创建完毕。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lyserver/archive/2008/10/01/3007090.aspx
阅读(1806) | 评论(0) | 转发(0) |
0

上一篇:NFS笔记

下一篇:openlog()和syslog()的用法

给主人留下些什么吧!~~