📄 cisserver.cpp
字号:
#include "CisPub.hpp"#include "BepsSend.h"/******************************************************************************* CisServer.bin的功能说明** 多进程管理** 接收从柜台发来的业务*****************************************************************************/#ifndef BOOL#endif#ifndef TRUE #define TRUE 1#endif//全局数据tagMyGlobe *myglobe = new tagMyGlobe;ComSocket_wzSer *comSocket;BepsPub sBepsPub;SybServer m_clsSybServer;//格式化字符串int StrTrimChar( char *in_data ,char c){ int i,j = 0; char tmp[1024]; memset(tmp,0,sizeof(tmp)); for(i = 0;i < strlen(in_data);i++) { if(in_data[i] != c) tmp[j++] = in_data[i]; } strcpy( in_data , tmp); return TRUE;}//主函数int main(int argc, char* argv[]){ //使主进程成为守护进程 pid_t main_pid =0; main_pid = fork(); if(0!= main_pid) { exit(0); } //调用初始全局数据函数 int iRetval; ComSocket_wzSer com; comSocket = &com; if(!InitGlobeData()) { errlog( "[CisServer.bin] 初始全局失败,程序退出" ); exit (-1); } //通讯插件开始工作 iRetval = comSocket->Open(); if(iRetval != 0) { errlog( "[CisServer.bin]通讯端口失败, 程序退出"); exit(-1); } while(1) //开始服务 { //进程控制 MonitorWorkFlag(); //子进程管理函数 在这里完成对新建子程序 iRetval = ManageChildProcess(); if(iRetval != 0) { filelog(CIS_SRV_LOG, "Create new process failed"); errlog( "进程[CisServer.bin]创建失败, 程序退出"); continue; } MonitorWorkFlag(); sleep(1); //复位接收到客户端的SOCKET,以便等待其他客户端的连接 comSocket->msocket_id = -1; } }///////////////////////////////////////////////////////////////////////////////// 处理信号子进程的函数int ManageChildProcess(){ //如果发现有客户端连接请求,则建立连接并创建新进程处理新连接SOCKET业务 if(0 == comSocket->Service()) { pid_t chiPid; //产生子进程操作 chiPid = fork(); if(chiPid < 0) { //如果FORK子进程失败那么设置工作标志为通知退出 myglobe->workFlag = FLAG_FORMEXIT; errlog( "[RecvFromM b.bin] 创建子进程失败"); return (-1); } if(chiPid == 0) { //子进程关闭监听套接口 comSocket->Close(comSocket->socket_id); //让和新客户端建立连接的进程自举,脱离父进程,成为守护进程 ChildProcess(); } if(chiPid>0) { //父进程关闭已经接受处理的套接字,由子进程去处理 comSocket->Close(); } } return 0;}/////////////////////////////////////////////////////////////////////////////////子进程的处理函数//设置SOCKET为非阻塞方式///int flag = fcntl(pMsSoket->connfd, F_GETFL, 0);///fcntl(pMsSoket->connfd, F_SETFL, O_NONBLOCK|flag);void ChildProcess(){ //开始子进程的具体处理 char sResDesc[MAX_MBFE_BUFFER]; char *RecvBuf = 0; int RecvBufLen = 0, SendBufLen = 0; int ret; char TrNo[100],TransNo[100]; int RetCode = 0, iRetval = 0; char *RetMsg = 0,*Result = 0; char PassWord[10]; char UserNo[20]; memset( UserNo , 0 , sizeof( UserNo )); memset( TransNo , 0 , sizeof( TransNo )); /* if(FALSE==sBepsPub.GetSysCtlPar(NUM_CONNECT, sysValue, resStr)) { printf("%s\n", resStr); delete pMsSoket; exit(-1); } filelog(CIS_SRV_LOG, "sysValue=[%s] sysConfig=[%s]", sysValue, myglobe->chiProcCount); if(atoi(sysValue)>atoi(myglobe->chiProcCount)) { pMsSoket->SentHeartMsg("000009NOCONNECT"); pMsSoket->Close(); disConnectToDB(); filelog(CIS_SRV_LOG, "Connect count is max and disconnect client=[%s]", pMsSoket->clientIp); exit(-1); } //sBepsPub.UpdateNumClient(ADD_CONNECT); int Xflag = 0; ret = sBepsPub.CheckSerail(&Xflag); if( Xflag != 0) { printf("system not permission exit\n"); exit(0); }*/ memset( PassWord , 0 , sizeof(PassWord)); strcpy( PassWord , getenv("PASSWORD")); char DBUserName[10]; memset( DBUserName , 0 , sizeof(DBUserName)); strcpy( DBUserName , getenv("DBUSERNAME")); StrTrimChar(DBUserName,' '); if( strlen( DBUserName ) == 0 ) { strcpy( DBUserName , "sa"); } printf("DBUserName = [%s]\n", DBUserName); ret = connectToDB( "SYBASE" , DBUserName, PassWord ,"DIRWAYSDB"); if( ret != 0 ) { comSocket->Close(); printf("\r\n DataBase connect error!!!"); errlog( "DataBase connect error!!!"); exit(-1); } RecvBuf = ( char *)malloc(MAXBUFF*sizeof(char)); Result = ( char *)malloc(MAXBUFF*sizeof(char)); RetMsg = ( char *)malloc(100*sizeof(char)); if( (NULL == RecvBuf) || (NULL == Result) || (NULL == RetMsg)) { printf("\r\n malloc error!!!"); filelog(CIS_SRV_LOG, "malloc error!!!\n"); disConnectToDB(); exit(-1); } //子进程开始服务 printf("\nPID=[%d] System start service....\n",getpid()); for(;;) { memset( RecvBuf, 0, MAXBUFF); memset( Result, 0, MAXBUFF); memset( RetMsg, 0, 100); memset( sResDesc, 0, MAX_MBFE_BUFFER); //收取信息 printf("\nPID=[%d] begin Recv....\n",getpid()); iRetval=comSocket->Recv(RecvBuf, RecvBufLen, RetCode, RetMsg); if ( iRetval != 0 && iRetval !=2 ) { //登陆失败,柜员状态不初始化 if( strncmp( TransNo , "10811" , 5 ) != 0) { printf("柜员退出,初始化柜员状态!\n"); sBepsPub.InitUserStatus(UserNo); }else{ printf("柜员登陆失败,不需要初始化柜员状态!\n"); } comSocket->Close(); //sBepsPub.UpdateNumClient(DEL_CONNECT); disConnectToDB(); free(RecvBuf); free(Result); free(RetMsg); filelog(CIS_SRV_LOG, "Disconnect from client and exit!\n"); printf("Disconnect from client and exit!\n"); exit(0); } //非法消息不处理 if( iRetval == 2) { continue; } if(strlen(RecvBuf) > 0 ) { RecvBuf[RecvBufLen] = '\0'; printf("\nRecv = [%d][%s]\n", strlen(RecvBuf),RecvBuf); filelog(CIS_SRV_LOG, "RecvBuff is:[%d][%s]\n", strlen(RecvBuf), RecvBuf); char *Begin = NULL,*End = NULL; memset(UserNo ,0 , sizeof( UserNo )); Begin = strstr( RecvBuf , ":LoginName:"); End = strstr( Begin + 12 , ":"); memcpy( UserNo , Begin + 11 , End - Begin - 11); printf("UserNo = [%s]\n", UserNo ); Begin = NULL; End = NULL; Begin = strstr( RecvBuf , ":TranNo:"); memcpy( TransNo , Begin + 8 , 5 ); printf("TransNo = [%s]\n", TransNo ); Begin = NULL; ret = sBepsPub.CisServer( TrNo , RecvBuf, Result, sResDesc ); if( ret <= 0 ) { errlog("交易处理失败[%s]\n",sResDesc); printf("交易处理失败[%s]\n",sResDesc); continue; } printf("++RecvBuf:[%s]\n", RecvBuf ); //printf("++Result:[%s]\n", Result ); //printf("++sResDesc:[%s]\n", sResDesc ); SendBufLen = strlen(Result); //返回处理结果 iRetval = comSocket->Send(Result,sResDesc,SendBufLen, &RetCode, &RetMsg); if ( iRetval != 0 ) { //sBepsPub.UpdateNumClient(DEL_CONNECT); filelog(CIS_SRV_LOG, "Send data failed and exit!\n"); printf("Send data failed and exit!\n"); continue; } } else { printf("非法消息丢弃不处理\n"); continue; }////////////////////////////////////////////////////* //每隔一分钟发送一次心跳消息 CurrTime = time(NULL); if((CurrTime-LastTime) >= 120) { if(0 != comSocket->SentHeartMsg("000010SND::HK; ")) { MaxHeartMsgFail++; } else { MaxHeartMsgFail=0; } LastTime = CurrTime; } //发送心跳失败的次数超过三次后进程退出 if(MaxHeartMsgFail >= 3) { sBepsPub.InitUserStatus(UserNo); comSocket->Close(); //sBepsPub.UpdateNumClient(DEL_CONNECT); disConnectToDB(); delete comSocket; free(RecvBuf); free(Result); free(RetMsg); errlog("发送三次心跳消息失败,系统正常退出"); filelog(CIS_SRV_LOG, "Send HeartMsg max times failed and exit!\n"); printf("Send HeartMsg max times failed and exit!\n"); exit(0); }*/// ssleep(1*10000L); }}///////////////////////////////////////////////////////////////////////////////// 处理信号SIGTERM函数void CatchSigTerm(int sig){ myglobe->workFlag = FLAG_FORMEXIT;} ///////////////////////////////////////////////////////////////////////////////// 处理信号SIGCHLD函数void CatchChild(int sig){ pid_t pid; int stat; //通知内核在没有己终止子进程时不要阻塞 while((pid = waitpid(-1, &stat, WNOHANG)) > 0) { //修改该子进程对应的状态 myglobe->mutex->SetChiProInfoEx(pid, csDead); }} ///////////////////////////////////////////////////////////////////////////////// 处理信号SIGINT函数void CatchSigInt(int sig){ KillAllChilPro(); exit (0);}///////////////////////////////////////////////////////////////////////////////// 强行关闭所有进程int KillAllChilPro(){ int I; pid_t pid; for(I = 0; I < atoi(myglobe->chiProcCount); I++) { pid = myglobe->mutex->GetChiProPid(I); if(pid > 0) { kill(pid, 9); } } return 0;}///////////////////////////////////////////////////////////////////////////////// 初始化全局数据bool InitGlobeData(){ //设置相关信号处理函数 signal(SIGINT, CatchSigInt); signal(SIGTERM, CatchSigTerm); if(!LoadConfig()) { errlog( "进程[CisServer]解析配置文件BepsSend.xml出错"); return false; } myglobe->workFlag = FLAG_RELOAD; //初始化互斥量 myglobe->mutex = new CMuTex(atoi(myglobe->chiProcCount)); return true;}///////////////////////////////////////////////////////////////////////////////// 监控系统工作标志int MonitorWorkFlag(){ //处理僵尸进程 signal(SIGCHLD, CatchChild); //轮询各子进程是否存在,如果不存在则关闭对应还存在的套接字 /*int pid = 0; for(int i=1; i<atoi(myglobe->chiProcCount); i++) { pid = myglobe->mutex->m_ChiInfo[i].m_chiPid; if(!myglobe->mutex->ChiProIsLive(pid)) { int socket = myglobe->mutex->m_ChiInfo[i].m_socket; if(socket != -1) { printf("Server is exit and disconect client\n"); comSocket->Close(socket); } } }*/ int result = 0; switch(myglobe->workFlag) { //正常流程 case FLAG_NORMAL: { break; } //重载配置 case FLAG_RELOAD: { break; } //进程退出 case FLAG_FORMEXIT: { KillAllChilPro(); disConnectToDB(); exit(0); } //未定义控制符 default: { break; } } return result;}// 从配置文件中读取配置参数bool LoadConfig(){ bool result = true; char conpath[50]; memset( conpath, 0x0, sizeof(conpath)); sprintf( conpath,"%s/etc/%s", getenv("WORKDIR"), CONFIGXML); myglobe->binconfig = new CBinConfig(conpath); result = myglobe->binconfig->IsReady(); if(result) { if(!(result = myglobe->binconfig->GetParameterValueByName("chiProcCount", myglobe->chiProcCount))) { printf("从XML中载入参数 [%s] 时出错\n", "chiProcCount"); } else if(!(result = myglobe->binconfig->GetParameterValueByName("loglevel", myglobe->loglevel))) { printf("从XML中载入参数 [%s] 时出错\n", "loglevel"); } else if(!(result = myglobe->binconfig->GetParameterValueByName("spasswd", myglobe->spasswd))) { printf("从XML中载入参数 [%s] 时出错\n", "spasswd"); } } printf("配置参数如下所示:\n"); printf("子进程的个数 [%s]\n", myglobe->chiProcCount); printf("与MBFE连接的密码 [%s]\n", myglobe->spasswd); printf("日志层次深度 [%s]\n", myglobe->loglevel); return result;}int connectToDB( char *dbname , char *username , char *passwd , char *wkname){ if(!m_clsSybServer.Open(dbname,username ,passwd)) { printf("连接数据库[%s][%s][%s]失败!\n",dbname,username,passwd); return -1; } if(!m_clsSybServer.SetWrkDb(wkname)) { printf("切换数据库[%s]失败!\n" , wkname); return -1; } return 0;}int disConnectToDB(){ m_clsSybServer.Close(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -