📄 sms.c
字号:
/*----------------------------------------------------------------
用AT命令发送手机短信的例子
作者:江振健(网名:慕容飞云)
http://www.my66.com
E_mail:litth@yeah.net
------------------------------------------------------------------*/
#include <stdio.h>
#include <conio.h>
#include <windows.h>
/*-------------------------------------------------------------
函数名 :PduCode
功能 :生成短信的PDU编码字符串.
参数 :cnt --短信服务中心号码,sdt--接收号码(对方手机号),msg--短信内容.
返回值 :经PDU编码的字符串指针,如有错,其内容为空.
---------------------------------------------------------------*/
char *PduCode(char *cnt,char *sdt,char *msg)
{
static unsigned char pdu[1024]="",tmp1[1024],tmp2[20];
int i,k,len_cnt=strlen(cnt),len_sdt=strlen(sdt),len_msg=strlen(msg);
memset(pdu,0,sizeof(pdu));//把存放PDU编码的内存清零.
if(len_cnt>18||len_sdt>18||len_msg>100)return pdu;//判断参数是否有效.
strcpy(tmp1,cnt);//把服务中心号复制到tmp1
if(len_cnt%2==1){strcat(tmp1,"F");len_cnt++;}//若服务中心号长度为奇数则追加"F".
sprintf(pdu,"%02X",(len_cnt/2)+1);//服务中心号码长度.
if(!strncmp(cnt,"00",2))//判断服务中心号类型.
{
strcat(pdu,"81");
}
else
{//默认短信服务中心号前有"+",如+86130200500.
strcat(pdu,"91");
}
for(k=strlen(pdu),i=0;i<len_cnt;i++,k++)
{//每两个字节位置交换.
pdu[k]=i%2==0?tmp1[i+1]:tmp1[i-1];
}
//处理接收方手机号码.
sprintf(tmp2,"1100%02X81",len_sdt);
strcat(pdu,tmp2);
strcpy(tmp1,sdt);
if(len_sdt%2==1)
{//若接收方手机号长度为奇数则追加"F".
strcat(tmp1,"F");
len_sdt++;
}
for(i=0,k=strlen(pdu);i<len_sdt;i++,k++)
{//每两个字节位置交换.
pdu[k]=i%2==0?tmp1[i+1]:tmp1[i-1];
}
//处理被发送的短信的内容.
k=2*MultiByteToWideChar(CP_ACP,//转换成UNICODE.
MB_PRECOMPOSED,msg,len_msg,(unsigned short *)tmp1,sizeof(tmp1));
sprintf(tmp2,"0008FF%02X",k);
strcat(pdu,tmp2);
for(i=0;i<k;i++)
{//将短信内容每两个字节位置交换转成十六进制的字符串.
sprintf(tmp2,"%02X",i%2==0?tmp1[i+1]:tmp1[i-1]);
strcat(pdu,tmp2);
}
return pdu;
}
/*-------------------------------------------------------------
函数名 :ATCommand
功能 :发送AT命令到指定的串口
参数 :hComm--串口的句柄,cmd--AT命令
返回值 :发送AT命令后收到的字符指针
---------------------------------------------------------------*/
char *ATCommand(HANDLE hComm,char *cmd)
{
DWORD readwrite=0;
static char buf[1024];
ZeroMemory(buf,sizeof(buf));
WriteFile(hComm,cmd,strlen(cmd),&readwrite,NULL);
Sleep(800);//等待调制解调器处理AT命令.
ReadFile(hComm,buf,sizeof(buf)-1,&readwrite,NULL);
printf("%s\n",buf);
return buf;
}
/*-------------------------------------------------------------
主函数
---------------------------------------------------------------*/
int main(int argc,char *argv[])
{
char buf[1024],*p,*sms,*center=NULL;
HANDLE hComm;
DCB dcb;
int len,len_center;
COMMTIMEOUTS cto = { 20, 10, 10, 10, 10 };
hComm=CreateFile("COM1",//注意:此参数视您手机与哪个串口相连而定,如COM1,COM3,COM5等.
GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
if(hComm==INVALID_HANDLE_VALUE)
{
printf("通信串口打开错误.");
goto Quit;
}
GetCommState(hComm,&dcb);
dcb.BaudRate = CBR_9600; // 设置波特率为9600.
dcb.ByteSize = 8; // 字节为 8位.
dcb.Parity = NOPARITY; // Parity 为 None.
dcb.StopBits = ONESTOPBIT; // 1 个停止位.
if (!SetCommState(hComm, &dcb)) {// 设置通信端口状态.
printf("通信串口设置错误.");
goto Quit;
}
SetCommTimeouts(hComm,&cto);//设置超时时间.
if(!strstr(ATCommand(hComm,"AT\r"),"OK"))//判断手机是否支持AT命令.
{
printf("通信串口未连接手机或手机不支持AT命令.\n");
goto Quit;
}
//取短信服务中心号码.
for(p=ATCommand(hComm,"AT+CSCA?\r");*p!='\0';p++)
{//从引号间找出服务中心号,如:+CSCA: "8613010200500",145.
if(*p=='"' && center!=NULL)
{
*p='\0';break;
}
if(*p=='"' && center==NULL)
{
center=p+1;
}
}
if(center==NULL)
{
printf("找不到服务中心号码.\n");
goto Quit;
}
sms=PduCode(center,"13026889xyz","电脑爱好者程序谷");//进行PDU编码.
if((len=strlen(sms)/2)<=0)
{printf("PDU编码失败.\n");
goto Quit;
}
len_center=strlen(center);
if(len_center%2==1)
{
len_center++;
}
len-=(len_center/2)+2;//计算短信内容长度.
ATCommand(hComm,"AT+CMGF=0\r");//发送AT+CMGF=0<CR>.
sprintf(buf,"AT+CMGS=%d\r",len);
ATCommand(hComm,buf);//发送AT+CMGS=n<CR>.
ATCommand(hComm,sms);//发送经PDU编码的字符串.
ATCommand(hComm,"\32\r");//发送(CTRL+Z+<CR>)结束.
Quit:
CloseHandle(hComm);//关闭句柄.
printf("任意键退出.");
getch();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -