在Linux下用C语言实现短信收发


 本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/lyserver/archive/2008/10/01/3007090.aspx
首先,我根据功能需要创建了几个头文件,一个是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<strlen(inbuff);i++)   <br="">    {   
        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<ilen;i+=4)   <br="">    {   
        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<strlen(inbuff);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<ilen;i+=4)
 {
  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<sizeof(speed_name) sizeof(int);i++)  ="" <br="">    {   
        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<sizeof(speed_name) sizeof(int);i++)<br=""> {
  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<iretry;i++)   <br="">    {   
        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<iretry;i++)   <br="">    {   
        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<iretry;i++)   <br="">    {   
        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<l;i+=2)   <br="">    {   
        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<strlen(psrccode);i+=2)   <br="">    {   
        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<iretry;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<iretry;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<iretry;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<l;i+=2)
 {
  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<strlen(psrccode);i+=2)
 {
  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
    至此,一个完整的短信收发程序已成功创建完毕。
 

转载于:https://www.cnblogs.com/wangliangblog/p/6229141.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值