⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄

📁 170话费催交系统
💻
字号:
  一. 线程

     1. 催缴主线程: 初始化语音卡,初始化数据库,判定催缴条件,
                    以及协调其它3个线程的工作。
     2. 催缴工作线程: 接受处理语音卡事件, 具体进行催缴工作。
     3. 数据库读处理线程: 从催缴表中取数据, 并判定是否可以对此
                          用户催缴, 再往主缓冲区中写数据。
     4. 数据库写处理线程: 每成功催缴一次用户, 即在催缴表中将此
                          用户的催缴次数加1。

     其中1,3线程使用分时方式处理,2, 4线程使用消息接收方式处理。

  二. 定制文件结构
     
     1. 多个线程共用的数据结构

        a.> 主数据缓冲区, 主缓冲区读写指针
            typedef struct main_cjdata{
                     char hth[HTH_LENGTH+1];           //合同号
                     char num[NUM_LENGTH+1];           //电话号码
                     char cuijiao[CJJE_LENGTH+1];     //催缴金额
                     char cjmonth[CJMONTH_LENGTH+1];   //欠缴月份
                     int  cjcount;                 //催缴成功次数
            }MAIN_CJDATA;
            主数据缓冲区大小定为100[MAINDATA_LENGTH],
            int readmain;         //读指针(0-99)
            int writemain;        //写指针(0-99)

        b.> 辅助数据缓冲区, 辅缓冲区读写指针
            typedef struct append_cjdata{
                     char hth[HTH_LENGTH+1];           //合同号
                     char num[NUM_LENGTH+1];           //电话号码
                     char cuijiao[CJJE_LENGTH+1];     //催缴金额
                     char cjmonth[CJMONTH_LENGTH+1];   //欠缴月份
                     int  cjcount;                   //催缴成功次数
                     int  append_count;              //进辅缓冲区的次数
            }APPEND_CJDATA;
            辅助数据缓冲区大小定为30[APPENDDATA_LENGTH],
            int readappend;         //读指针(0-29)
            int writeappend;        //写指针(0-29)

        c.> 重拨次数
            int cbcount;       //即进辅缓冲区的最大次数

        d.> TCB线程通信块
            typedef struct TreadCtrlBlock{
                    unsigned int chdevno;       //通道号
                    CWinThread * pThreadOfDbms; //数据库线程指针
            }TCB;
            用来在催缴工作线程和数据库写处理线程之间通讯

        e.> 语音卡通道数据块
            typedef struct ch_info{
                    long chdev;               //通道号(通道指针)
                    int chdevzt;             //通道当前所处的状态
                    int playflag;            //播音标志
                    int chtime;              //max over time
                    _CAP callp;              //parameters for PerfectCall
                    Tone_T tmplts[MAX_TONES]; //PerfectCall tone definitions
                    int volPos;               //current volume setting for playback
            }CH_INFO;
            主线程打开通道,取得通道指针并写入语音卡通道数据块。
            催缴线程具体处理催缴工作。

        f.> long chdev[MAXDEVS];      //催缴通道指针队列
            int devcounts;           //当前用于催缴的通道数目
            催缴通道指针队列长度30,并与语音卡通道一一对应,如果某通道工作于催缴
            方式,队列中对应的位置即写入该通道的指针,如果某通道未工作于催缴方式,
            队列中的对应位置即写入-1。
            
      二. 主线程使用的数据结构
          a.> 信号灯原状态             
              typedef struct old_signlight{
                      long   chdev;           //通道号(通道指针)
                      int   workzt;          //原工作方式(催缴,查询或未用)  
              }OLD_SIGNLIGHT;
              大小定义为30[MAXDEVS], 保存所有通道原先的工作方式。在查询信号灯时,
               若某通道工作于催缴方式,即比较该通道的原工作方式,如果原先不是
              工作于催缴方式,则需对此通道进行催缴初始化处理[Init_cuijiao(long chdev)],
              并将通道指针加入催缴通道指针队列。如果原先是工作于催缴方式,则无须处理。
               若某通道未工作于催缴方式,也比较该通道的原工作方式,如果原先工作于
              催缴方式,则需将该通道的指针从催缴队列中删除。如果原先未工作于催缴方式,
              则无须处理。              
              (这种方式等待的指针队列与通道号一一对应,长度为30,未工作于催缴方式的指针设
              为空,工作于催缴方式的则设为该通道的指针) 
          b.> 催缴参数
               typedef struct cj_time{
                       int start_month;        //催缴起始和终止时间段
                       int end_month;
                       int start_day;
                       int end_day;
                       int start_hour;
                       int end_hour;
                       int start_minute;
                       int end_minute;
               }CJ_TIME;
               
               typedef struct cj_arg{
                       CJ_TIME cjtime[3];      //定制三个催缴时间段
                       int cjtime_one;         //时间段一的启用标志(0不启用,1启用)  
                       int cjtime_two;         //时间段二的启用标志(0不启用,1启用)
                       int cjtime_three;       //时间段三的启用标志(0不启用,1启用)
                       int cb_count;           //重拨次数
                       int max_count;          //催缴最大次数
                       int maxcount_flag;      //是否使用催缴最大次数的标志(0不使用,1使用)
               }CJ_ARG;

      三. 催缴工作线程用到的数据结构
      四. 数据库读写线程用到的数据结构
   
A.dll调用 
 extern "C" __declspec(dllexport) double SquareRoot(double d);
下面是应用程序对该导出函数的显式链接的例子:
typedef double(SQRTPROC)(double);
HINSTANCE hInstance;
SQRTPROC* pFunction;
VERIFY(hInstance=::LoadLibrary("c:\\winnt\\system32\\mydll.dll"));
VERIFY(pFunction=(SQRTPROC*)::GetProcAddress(hInstance,"SquareRoot"));
double d=(*pFunction)(81.0);//调用该DLL函数
 
B.生成lib库
  对于一些常用到的函数,可以生成一个lib库来调用,方法是生成一个lib的project,
  然后编译成一个lib。 只是要注意lib函数对于外部变量的操作必须使用参数传递的方法带入
  带出,否则生成的lib无使用价值,编译生成lib之后,以后要用到lib中的函数时,只要将lib
  的头文件加入到编制的project的include中,以及将lib加入到project的link中,就可以正
  确使用了。(c和cpp的lib均可用同样的方法生成)
C.多个cpp使用相同的变量的方法
  在一个头文件中定义好该变量,然后对于该变量再定义一个extern的外部说明,使用的时候
  在各cpp中包含这个外部说明即可。
   
D.link时用到的标准库  
 version.lib libdtimt.lib libdxxmt.lib sctools.lib libgc.lib libfaxmt.lib libsrlmt.lib
 
E.ODBC驱动
  Microsoft ODBC for Oracle 版本 2.573.3711.00 MSORCL32.dll 01/01/99
  此版本的ODBC可支持自动重连,即当网线断开,与服务器失去连接时,此驱动会在
  网络恢复连接后自动再连上服务器数据库。(超时60s,重试等待时间120s,这两个参
  数ODBC数据源管理器中可设置)
  但是对于服务器杀掉连接进程后,这个ODBC不能自动修复连接,仍需编程修复

五. 实时读取数据催缴
	催缴的新条件:2001.02.15
 	催缴表每月生成一次,但是生成后会实时的更新。

 	催缴时必须能指定催缴的合同号,催缴合同号可能是连续的或是间断的。
    2001.02.19
   	 催缴方式进行了一次较大的变动,就是将读数据设定在催缴时间段内进行,而催缴时间段外不读取数据,
    因为催缴数据实时更新,若读数据在催缴时间段外进行,则有可能出现原先读到缓冲区内的数据已经更新,但
    催缴系统却不知道,而在下一个催缴时间段继续按原有数据拨打催缴电话,出现错误催缴的情况。
    	将读数据改为在催缴时间段内进行后,系统即时读取数据,即时催缴,不会有较大的时间间隔。当时间到达
    催缴时间段外时,系统将停止读数据,而且会将缓冲区内剩余的催缴数据全部拨出,不会留下老数据在缓冲区内。
    这样就可以实现催缴数据的实时更新,实时催缴,不会出现用户交费之后,还接到催缴电话的情况。
    	相对原来的催缴读数据方式,只是催缴速度略有降低,其它没有影响。
    	
  六. 催缴数据更新方式
       根据计费服务器上是否存在xtcj170.flag 文件来决定是整表传输还是更新传输。
       计费服务器10.88.93.2 /data2/xtydj/xtcj170.flag
       170服务器`10.88.92.8 /u1/xt170/ftpd/data/xtcj170.flag
       
  2000.2.21
  试运行中出现的问题
  	1. 有两个通道在试运行时阻塞在两个号码的振铃状态,虽然有超时处理机制,
  	但隔了一天也没有恢复。
  		一.可能原因
  		a.(yin_seize)运行到
  		if((tsbits=ATDT_TSSGBIT(dxinfo[i].dtdev))==AT_FAILURE){
			TRACE("ATDT_TSSGBIT() error");
			return -1;
		}
		出错
		b. 问题可能是两个通道的信号灯状态没有置为空闲,所以
  		催缴系统就无法再使用这两个通道。
  		二.解决方案
  		a.自动修复:使用系统超时处理机制,每隔10分钟检测一下各通道是否长时间处于工作
  		状态,若是则关闭该通道然后再重新打开。
  		b.手工修复:每个通道均在界面上提供一个按纽,此按纽可完成重新打开某一通道的功能。
  		(a,b方案同时采用)
  		(已修改,待测试)
  	2. 有些记录写日志不成功
  	3. 日志记录不完整,有的日志记录只有合同号
  	4. 少数催缴标志为9的也被催缴
  	   原因
  	   a.由于所打开的催缴记录集使用了缓冲区,造成了虽然数据库内的记录已经更新,但是催缴记录集
  	   却没有更新,所以系统仍按旧数据进行催缴。
  	   解决方案:
	   a. 重建一个催缴记录集,使用动态连接读数据(暂选a方案) (已修改,待测试)
	   b. 每更新一次数据,即重新检索一次。	  	   
  	5. 读异常恢复后,应从旧有位置继续往下读 (已修改,待测试)
  
  2000.2.22
  	改变了记录日志的方式,即在某通道播完催缴音后,系统挂机同时向记录日志线程发送消息,但此时该
  	通道的信号灯未置位,催缴数据未清除,所以此通道不会用来催缴下一个号码,而直到日志记录完成后,
  	此通道的信号灯才置为空闲状态,同时清除催缴数据,再用它来催缴其它号码。
  		原方式是等日志记录完成后才挂机,这就可能造成通话完成后,用户仍须等待一段时间,系统才
  	会挂断电话。新方式是通话完成即挂机,使接电话的用户不会有空等的时间,新的日志记录方式更合理。
  
  程序运行到读记录第5211时,就不再往下读了。
  可能原因:待查
   现象:第5211条数据合同号有误,且无催缴金额
   原因:系统遇到合同号或金额为空的记录即忽略,但是忘记将记录指针下移,以至
   在被忽略的记录处陷入死循环。
   (已解决,待测)
   
   2000.2.23
   	日志记录不完整,有部分催缴成功的用户并没有写入日志。
   	原因:odbc往数据库写的时候速度较慢,使得部分数据未来得及写入数据库就已达到超时时间。
   	解决方案:
   	a. 将记录日志超时时间定长到60秒。(暂选)
   	b. 写数据库使用pb,不用odbc。
   	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -