📄 mon_test.c
字号:
// 监控程序
// POS-前置机间电文全局说明
// 起始位 电文长度 传输协议数据单元 交易数据(含MAC) 停止位 校验和
// 1位 2位 5位 1位 1位
// 起始位-------------用以同步POS和前置机间通讯的数据位,并非8583规定。一般定为X’02’。
// 电文长度-----------此项长度为2字节,用于指示一段完整电文的长度。它的传输格式为BCD。举例来说,它用X‘0122‘表示电文长度为122Bytes。?注意此长度不含它本身的2字节,不含起始位1字节,不含停止位1字节,不含校验和1字节。因此它的值为整个完整电文长度减5。
// 传输协议数据单元---长度为5字节,它的传输格式为X‘60xxxx’。它在网控器通讯中起数据分流作用。
// 交易数据-----------涉及应用的具体数据,采用ISO8583标准进行组织,各域按位序号递增排列。
// 停止位-------------对应起始位,并非8583规定。一般定位X’03’。
// 校验和-------------用以确保POS-前置机间电文正确传输的手段,各厂家均采用相同算法。
// 交易数据部分(包括各bitmap位)的详尽描述
// ISO8583规定,任何交易电文数据的格式应该是这样的:
// 信息类型 位图表 相应于位图表的数据元素(不含位图表)
// 系统对各种信息类型已做定义,均为4位数字,应采用BCD格式传输,占2字节。例如POS联机签到的信息类型的传输格式为X‘0800’。
// 位图表为1或2个字节的索引表,它通过将各bit置0或1来指示各域的使用情况。位图表本身总是占有第一域,虽如此,位图表的第一bit还是被置为0。
// 除位图表以外、按域号递增顺序排列的其余各数据元素。
#include <stdio.h> /* Standard input/output definitions */#include <string.h> /* String function definitions */#include <unistd.h> /* UNIX standard function definitions */#include <fcntl.h> /* File control definitions */#include <errno.h> /* Error number definitions */#include <termio.h> /* POSIX terminal control definitions */#include <sys/time.h>#include <sys/select.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <time.h>#include <math.h>#include <stdlib.h>#include <sys/signal.h>#include "posmsg.c"
#include "comport.c"
#include "tools.c" // 一些转换函数
//#include "buflist.c" // 双向链表
#define PROMPT "你想终止程序吗?\n"
char *prompt = PROMPT;
int msqid;
int iPortDevice,oPortDevice;char * chrHostName = "localhost"; // bad functionint iPort; // = 11001;long dnum=0,znum=0,snum=0,fnum=0,xnum=0;//待处理数 当前进程数 处理成功数 处理失败数 需处理数/**************************** start of tools ****************************/char addCheckByte(u_char *buffer,int len){ char lrc='\x00',etx='\x03'; // stop byte int i=0; for(i=0;i<(len+2);i++){ // len + 2Byte包长度 lrc ^=buffer[i]; } lrc ^=etx; // 与1Byte停止位异或 return lrc;}void getTPDU(unsigned char *buffer,unsigned char *tpdu){ //取传输协议数据单元 int i=0; for(i=0;i<5;i++) tpdu[i]=buffer[i+3];}void chgTPDU(u_char *in,u_char *out){ out[0]=in[0]; out[1]=in[3]; out[2]=in[4]; out[3]=in[1]; out[4]=in[2];}void setPackLen(int len,char *packlen){ int temp1; int temp2; //printf("Len=%d\n",len); temp1=len/100; temp2=len%100; //printf("temp1=%d\n",temp1); //printf("temp2=%d\n",temp2); packlen[0]=(temp1/10)<<4 | temp1%10; packlen[1]=(temp2/10)<<4 | temp2%10; packlen[2]='\0'; //printf("packlen[0]=%02x\n",packlen[0]); //printf("packlen[1]=%02x\n",packlen[1]);}void resPackage(u_char *pack,u_char *tpdu,int len,u_char *buffer){ char stx='\x02'; //起始标记 char etx='\x03'; //结束标记 char lrc='\x00'; //校验位 char *packlen; //长度 u_char *rcvtpdu; //协议数据域 int i; packlen=(char *)malloc(3); memset(packlen,0x0,3); rcvtpdu=(u_char *)malloc(5); memset(packlen,0x0,5); //set STX buffer[0]=stx; //printf("buffer[0]=%02x\n",buffer[0]); setPackLen(len+5,packlen); buffer[1]=packlen[0]; buffer[2]=packlen[1]; //change TPDU chgTPDU(tpdu,rcvtpdu); /* for(i=0;i<5;i++){ printf("tpdu[%d]=%02x-chg-",i,tpdu[i]); printf("%02x\n",rcvtpdu[i]); } */ for(i=0;i<5;i++) buffer[i+3]=rcvtpdu[i]; for(i=0;i<len;i++) buffer[i+8]=pack[i]; //set ETX buffer[len+8]=etx; buffer[0]=stx; //??? //set lrc buffer[len+9]=addCheckByte(buffer+1,len+5); //end buffer[len+10]='\0'; //printf("\n打包后返回数据:\n"); //for(i=0;i<len+10;i++) // printf("Receive Package[%d]=[%02x]\n",i,buffer[i]); free(packlen); free(rcvtpdu);}void mylog(char *filename,char *log,int len){ FILE *fd; int k; if( (fd = fopen( filename, "a+" )) == NULL ){ printf("\n\r[ERROR]: Open log file failure\n" ); exit(0); } printf("\n\r写日志\n" ); fwrite(log,sizeof(char),len,fd); fflush(fd); fclose(fd);}//读二进制文件
int readfile(char *filename,unsigned char *buf){
FILE *stream;
int ch ,len = 0;
if( (stream = fopen( filename,"rb")) == NULL ){
printf( "文件打开失败!\n" );
return -1;
}
while ((ch = fgetc(stream)) != EOF){
buf[len++] = (unsigned char)ch;
// printf( "[%02x]",ch );
}
fclose( stream );
return len;
}
/**************************** end of tools ****************************///显示状态信息
void disp_sta(int x,int y,int code){
switch(code){
case 0: printf("\033[%d;%dH%s",x,y," ");
break;
case 1: printf("\033[%d;%dH%s",x,y,"正常");
break;
case 2: printf("\033[%d;%dH%s",x,y,"无效交易");
break;
case 3: printf("\033[%d;%dH%s",x,y,"无效返回码");
break;
case 4: printf("\033[%d;%dH%s",x,y,"不允许交易");
break;
case 5: printf("\033[%d;%dH%s",x,y,"超出限额");
break;
case 6: printf("\033[%d;%dH%s",x,y,"响应超时");
break;
case 7: printf("\033[%d;%dH%s",x,y,"交易成功");
break;
case 8: printf("\033[%d;%dH%s",x,y,"无效操作");
break;
case 9: printf("\033[%d;%dH%s",x,y,"格式错误");
break;
case 10: printf("\033[%d;%dH%s",x,y,"向串口写回应报文给NCA...");
break;
case 11: printf("\033[%d;%dH%s",x,y,"从 com 接收需处理的数据");
break;
case 12: printf("\033[%d;%dH%s",x,y,"向 socket 送需处理数据...");
break;
case 13: printf("\033[%d;%dH%s",x,y,"没有得到 com 数据!");
break;
case 14: printf("\033[%d;%dH%s",x,y,"接收已处理数据...");
break;
case 15: printf("\033[%d;%dH%s",x,y,"写完串口!");
break;
case 16: printf("\033[%d;%dH%s",x,y,"没有得到 socket 数据!");
break;
case 17: printf("\033[%d;%dH%s",x,y,"没有读到串口数据!");
break;
default: printf("\033[%d;%dH%s",x,y," ");
}
}
void draw_monitor_screen(){
// int i;
printf("\033[2J\n"); printf("\033[4;1H┌──────────────────────────────────────┐");
printf("\033[5;1H│ 农信POS交易系统V1.0 -- 交易监控屏幕 │");
printf("\033[6;1H├──────┬──────────┬────┬───┬────┬──────┤");
printf("\033[7;1H│待处理数 │正处理数 │成功数 │失败数│需处理数│当前状态 │");
printf("\033[8;1H├──────┼──────────┼────┼───┼────┼──────┤");
// for(i=0;i<10;i++)
// printf("\033[%d;1H│ │ │ │ │ │ │",i+9);
printf("\033[9;1H│ │ │ │ │ │ │");
printf("\033[10;1H├──────┴──────────┴────┴───┴────┴──────┤");
printf("\033[11;1H│提示∶ │");
printf("\033[12;1H└──────────────────────────────────────┘");
// printf("\033[%d;%dH%s",13,2,"待处理的数据");// printf("\033[%d;%dH%s",22,2,"已处理的数据");}
// 更新监视数据
void upinfo(){
uchar buf[30];
printf("\033[%d;%dH%d",9,5,dnum);
printf("\033[%d;%dH%d",9,20,znum);
printf("\033[%d;%dH%d",9,40,snum);
printf("\033[%d;%dH%d",9,50,fnum);
printf("\033[%d;%dH%d",9,60,xnum);
disp_sta(9,70,1);
return;
}
// 显示交易数据信息
void dispdata(int current,unsigned char * pub,int len){
uchar buf[30],i,dispflg;
unsigned long amount;
printf("\033[%d;%dH\n",current,0);
for (i=0;i<len;i++) printf( "[%02x]",pub[i] );
return;
}// 处理信号void ctrl_c_op(int signo){
char c;
write(STDERR_FILENO,prompt,strlen(prompt));
fflush(stdin);
c = getchar();
if (c == 'y'|| c == 'Y'){
delmsg(msqid);// 删除待处理消息队列
exit(0);
}
}
//主程序int main(int argc,char *argv[]){ unsigned long addrlong; unsigned char buffer[2048],rcvBuf[1024],rcvPack[1024],tpdu[6]; int rcvLen = 0,packlen,rec,i,fdw,fdr,loglen,pMaxNum; char *pCOM,logfile[10]="jznx.log",logmsg[1024]; struct sigaction act; // 设置退出信号
int msgqtype; // 1 为从 com 到 mon ,2 为从 mon 到 socketc ,3 为从 socketc 到 mon // act.sa_handler = ctrl_c_op;
sigemptyset(&act.sa_mask); // 将信号集合设置为空
act.sa_flags = 0;
if(sigaction(SIGQUIT,&act,NULL) < 0){ // CTRL-\ 退出当前进程,并生成主存储文件
fprintf(stderr,"Install Signal Action Error:%s\n\a",strerror(errno));
exit(1);
}
if(argc>2){ // 得到输入参数(串口设备名,Socket端口,调试输出标致) pCOM=argv[1]; pMaxNum=atoi(argv[2]); }else{ strcpy(logmsg,"\nPlease input Serial port & max process number, eg:\nmon /dev/tty2a 10\n"); loglen=strlen(logmsg); logmsg[loglen]='\0'; mylog(logfile,logmsg,loglen); // 写日志 printf("%s",logmsg); exit(0); } if( (fdw=open(pCOM,O_WRONLY))<0||(fdr=open(pCOM, O_RDONLY))<0){ // 打开读写端口 memset(logmsg,0,100); strcpy(logmsg,"\n\r[ERROR]: Open serial port for write failure\n"); loglen=strlen(logmsg); logmsg[loglen]='\0'; mylog(logfile,logmsg,loglen); // 写日志 return (-1); } setAttr(fdr); setAttr(fdw); setNowait(fdr); setNowait(fdw);
msqid = createmsg(0777|IPC_CREAT); // 创建消息队列的 server 端
draw_monitor_screen(); printf("\n"); while(1){ printf("\n开始从串口读数据...\n"); packlen = 0; rec = readPort(fdr,buffer,&packlen); printf("读到 %i 个数据.\n",packlen); if(rec < 1){ printf("没有读到 %s 上的数据!\n",pCOM);// disp_sta(11,9,-1);
// disp_sta(11,9,17);
buffer[0] = '\0'; packlen = 1; }else{ printf("向 mon 送待处理数据...\n"); xnum++; // 需处理数据数加一
dnum++; // 待处理数据数加一
} msgqtype = 1; sendmsgs(buffer,packlen,msqid,msgqtype); // 发送待处理的数据
if (znum < pMaxNum){
printf("从 com 接收需处理的数据\n");// disp_sta(11,9,-1);
// disp_sta(11,9,11);
msgqtype = 1; packlen = receivemsg(buffer,msqid,msgqtype); // 接收需处理的数据 }else{ // 进程上限发空数据
msgqtype = 1; buffer[0] = '\0';
packlen = 1; }
if(buffer[0] <> '\0'){ // 有需处理的数据 getTPDU(buffer,tpdu); // 取得传输协议数据单元 znum++; // 正处理数据数加一
printf("向 socket 送需处理数据...\n");// disp_sta(11,9,-1);
// disp_sta(11,9,12);
// for(i=14;i<21;i++) disp_sta(i,1,0);
// dispdata(13,buffer,packlen); // 显示交易需处理数据信息
}else{
printf("没有得到 com 数据!\n");// disp_sta(11,9,-1);
// disp_sta(11,9,13);
}
msgqtype = 2; sendmsgs(buffer,packlen,msqid,msgqtype); // 发送需处理的数据
printf("启动SOCKET进程...\n"); system("socketc 11001 30 0&"); // socket 端口,进程生存时限(秒),调试信息标致
printf("接收已处理数据...\n");// disp_sta(11,9,-1);
// disp_sta(11,9,14);
msgqtype = 3; packlen = receivemsg(buffer,msqid,msgqtype); // 接收已处理的数据 if( buffer[0] <> '\0'){ // 有已处理的数据 snum++; // 处理成功数加一 znum--; // 正处理数据数减一 dnum--; // 待处理数据数减一 printf("报文打包...\n");// dispdata(22,buffer,packlen); // 显示交易已处理数据信息
rcvLen = packlen+10; memset(rcvPack,0,rcvLen); resPackage(buffer,tpdu,packlen,rcvPack); // 打包 printf("向串口写回应报文给NCA...\n");// disp_sta(11,9,-1);
// disp_sta(11,9,10);
writePort(fdw,rcvPack,rcvLen); // 写串口 printf("写完串口!\n");// disp_sta(11,9,-1);
// disp_sta(11,9,15);
}else{
if (packlen > 1){ fnum++; // 处理失败数加一 znum--; // 正处理数据数减一 dnum--; // 待处理数据数减一 } printf("得到 socket 空数据!\n");// disp_sta(11,9,-1);
// disp_sta(11,9,16);
}
// upinfo(); // 更新监视数据
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -