2006毕业设计Delphi篇(三)

           上一次我们讲过了GPRSServer那个模块,这结我们讲ClientIn这个模块。上一节我留下一个东西没有讲,就是CutReceiveData这个函数,这个函数其实很大,涉及到的内容也很多,当然也涉及到一些商业机密。你们只要知道它是用来解包的就可以了,当然也可以把CutReceiveData做成一个类,但我没有这样做,速度和编程规范两者要我选择的话,我一般会选择速度,虽然我这段时间一直在写模式设计这个体系的东西,但我编程一般的原则是,能用结构绝不用类,能用函数决不用结构,能用指针决不用高级方法,关键方法的编写用汇编而不用函数,尽量避免用接口,能用GOTO的决不用Break,尽量将所有的程序做到一个模块中,当然还有能用别人的代码的就用别人代码。这样做可以最大限度的保证高速度。因为我觉得评价一个程序的好坏的指标就是:运行速度,稳定性,可扩展性,外延深度。代码好不好看是次要的。别人用的是你的程序而不是看你的语法。
        下面我们看看ClientIn是如何工作的。
我们先来看看这个模块总的结构:

 1 unit UnitClientIn;
 2
 3 interface
 4
 5 uses
 6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 7   Dialogs,unitmain,unit1message,UnitProtocal,UnitMatch, ScktComp,IniFiles,
 8   StdCtrls, ComCtrls, ToolWin, Menus,DateUtils,ComObj, ExtCtrls;
 9
10 type
11   TFormClientIn  =  class(TForm)
12     ToolBar1: TToolBar;
13     ToolButton1: TToolButton;
14     ToolButton2: TToolButton;
15     ToolButton3: TToolButton;
16     ToolButton4: TToolButton;
17     Memo1: TMemo;
18     ToolButton5: TToolButton;
19     SaveDialog1: TSaveDialog;
20     PopupMenu1: TPopupMenu;
21     SaveInfo1: TMenuItem;
22     ServerJava: TServerSocket;
23     TimerSend: TTimer;
24     TimerSendJ: TTimer;
25     Timer54: TTimer;
26      procedure  FormCreate(Sender: TObject);
27      procedure  ToolButton1Click(Sender: TObject);
28      procedure  ToolButton2Click(Sender: TObject);
29      procedure  ToolButton3Click(Sender: TObject);
30      procedure  ToolButton4Click(Sender: TObject);
31      procedure  ToolButton5Click(Sender: TObject);
32      procedure  SaveInfo1Click(Sender: TObject);
33      procedure  FormDestroy(Sender: TObject);
34      procedure  ServerJavaClientError(Sender: TObject;
35       Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
36        var  ErrorCode:  Integer );
37      procedure  ServerJavaClientRead(Sender: TObject;
38       Socket: TCustomWinSocket);
39      procedure  ServerJavaClientConnect(Sender: TObject;
40       Socket: TCustomWinSocket);
41      procedure  ServerJavaClientDisconnect(Sender: TObject;
42       Socket: TCustomWinSocket);
43      procedure  TimerSendTimer(Sender: TObject);
44      procedure  TimerSendJTimer(Sender: TObject);
45      procedure  Timer54Timer(Sender: TObject);
46
47   private
48      procedure  WMCopyData( var  M:TMessage);Message WM_COPYDATA;
49      Procedure  ReMessage( Var  Msg:TMessage);Message ServerSendToClientIn;
50      procedure  ClientTimerSend( var  Msg:TMessage);message ClientTimer;
51      Procedure  JEndFlgMessage( Var  Msg:TMessage);Message JEndFlgM;
52      Procedure  JPacketIDFlgMessage( Var  Msg:TMessage);Message JPacketIDM;
53      procedure  AddErrorToLine( Var  Msg:TMessage); Message SendToClientInError;
54    public
55      procedure  Set_SocketInfo(S:String);
56      procedure  SendMessageTo(hwndSend: HWND; s: String;
57   Mg:DWord;Wparam: Word; Flg: boolean);
58    procedure  AppException(Sender: TObject; E: Exception);
59     function  Change(B:byte):byte;
60     end ;

总体上来说这个模块里的函数并不多,为什么很少呢?因为这个模块的功能主要是将我们上章讲的GPRSServer模块处理好的数据包转发给Java后台,同时将Java后台发送过来的数据包分析后转发给GPRSServer模块,让GPRSServer模块发给下位机。所以数据解析的大部分工作都让GPRSServer里的CutReceiveData给做掉了。我们来看看他的第一个任务是如何完成的。

   第一个任务:转发GPRSServer送过来的数据,因为GPRSServer已经将下位机传送上来的数据解析成了电量电压电流等等数据了,所以我们的ClientIN只要做:收到——〉确认——〉发给Java后台就OK了。

看看转发的代码:(我真的受不了了,才写好的文章,被博客网一停止响应给毁了,还要重写)

 1 procedure  TFormClientIn.WMCopyData( var  M: TMessage);
 2 var
 3 Count ,i,l: integer ;
 4 PP:Pchar;
 5 S,SS,sss,GPRSIDSTR,SSS_Old:string; // 测试用
 6 hwndReceiver:HWND;
 7 label H1;
 8 begin
 9 if  (PcopyDataStruct(M.LParam) ^ .dwData = ServerSendToClientInInfo)  then
10     begin
11       S: = Pchar(PCopyDataStruct(M.LParam) ^ .lpData);
12        Count : = ServerJava.Socket.ActiveConnections;
13      for  i: = 0   to   Count - 1  do
14         begin
15       ServerJava.Socket.Connections [ i ] .SendText(S);
16         end ;
17       if  G_ShowInfo  then
18        Memo1.Lines. Add (S);
19     end ;
20       if   (PcopyDataStruct(M.LParam) ^ .dwData = ServerInSendToClientInInfo)  then
21        begin
22      S: = Pchar(PCopyDataStruct(M.LParam) ^ .lpData);
23      memo1.Lines. Add ( ' ClientIn<--ServerIn:收到数据! ' + S + # 13 + # 10 );
24      sss: = S;
25      SSS_Old: = S;
26       SS: = '' ;
27       GPRSIDSTR: = '' ;
28        ////////////////////////////////
29        ///
30        ///  假如为GPRS数据包则先进行拆包,对内部数据包进行打包后再进行合包,发送到TFormServer后再进行具体发送
31        ///  包格式为: %%%%| 13851823257 | #### | 后面格式不变
32        /////////////////////////////////
33        if  copy(sss, 1 , 5 ) = ' %%%%| '   then
34            begin
35              GPRSIDSTR: = copy(sss, 1 , 17 );
36              sss: = copy(sss, 18 , 1024 );
37            end ;
38        ///////////////////////////////////////////////////////////////////////////////
39        //
40        // 对9520H,J进行打包
41        ///////////////////////////////////////////////////////////////////////////////
42        if   copy(sss, 1 , 5 ) = ' ####| '   then
43              begin
44                      Goble_S: = '' ;
45                     SS: = IPro.BulidSendData(sss);
46                      if  SS = ''   then
47                        goto  H1;
48
49                      if  copy(SSS_Old, 1 , 5 ) = ' %%%%| '   then
50                         begin
51                         SS: = GPRSIDSTR + SS;
52                         hwndReceiver: = findwindow( ' TFormGPRSServer ' ,nil);  // 向GPRS服务器发送数据
53                             if   hwndReceiver <> 0   then
54                          SendMessageTo(hwndReceiver,SS,ClientInSendToGPRSServer, 0 ,true);
55                          end   else
56                          begin
57                          hwndReceiver: = findwindow( ' TFormServer ' ,nil); // 向无线电服务器发送数据
58                             if   hwndReceiver <> 0   then
59                          SendMessageTo(hwndReceiver,SS,ClientInSendToServerInfo, 0 ,true);
60
61                          end ;
62                     H1:
63    end ;
64        end ;
65 end ;

其实这个消息函数中涉及到ClientIn转发功能的也只有9~19行,上面的15行就是将GPRSServer发送过来的数据包通过Socket转发给JSP后台。我们从上面的代码中可以看出ClientIn模块并没有对这些数据包做容错处理,因为我们在GPRSServer模块中已经做过容错处理了,就是在我上面讲的CutReceiveData中。当然我们还会在Java后台中再作一次容错处理,但是在Java后台中作的容错操作要比在CutReceiveData中做的容错要简单得多了。
     当然我们在GPRSServer模块和Java后台的通讯上也作了很多的约定,比如说数据包如何转换,数据包的格式之类的东西,有很多,我写了大概有一本书之多。为什么要有这些约定呢?你们可能要问,直接将Java后台发送的数据包传送给底层模块不就行了吗。还需要这么麻烦用GPRSServer和ClientIN来转发吗。这个里面涉及到一些语言之间的差别,我们下一章再说。

第二个任务:ClientIN 将Java后台发送过来的数据包解析之后发送给GPRSServer模块。

 我们来看看转发代码:

 1 procedure  TFormClientIn.ServerJavaClientRead(Sender: TObject;
 2   Socket: TCustomWinSocket);
 3 var
 4 Count ,i,j: integer // 测试用
 5 S,SS,sss,GPRSIDSTR,SSS_Old:string; // 测试用
 6 hwndReceiver:HWND;
 7 label H1;
 8    begin
 9  try
10 while  socket.ReceiveLength > 0  do
11    begin
12      Goble_S: = '' ;
13      Goble_S: = socket.ReceiveText;
14      memo1.Lines. Add ( ' ClientIn<--JavaServer:收到数据! ' + Goble_S + # 13 + # 10 );
15      sss: = Goble_S;
16      SSS_Old: = Goble_S;
17       SS: = '' ;
18       GPRSIDSTR: = '' ;
19        ////////////////////////////////
20        ///
21        ///  假如为GPRS数据包则先进行拆包,对内部数据包进行打包后再进行合包,发送到TFormServer后再进行具体发送
22        ///  包格式为: %%%%| 13851823257 | #### | 后面格式不变
23        /////////////////////////////////
24        if  copy(sss, 1 , 5 ) = ' %%%%| '   then
25            begin
26              GPRSIDSTR: = copy(sss, 1 , 17 );
27              sss: = copy(sss, 18 , 1024 );
28            end ;
29        ///////////////////////////////////////////////////////////////////////////////
30        //
31        // 对9520H,J进行打包
32        ///////////////////////////////////////////////////////////////////////////////
33        if   copy(sss, 1 , 5 ) = ' ####| '   then
34              begin
35                      Goble_S: = '' ;
36                     SS: = IPro.BulidSendData(sss);
37                      if  SS = ''   then
38                        goto  H1;
39
40                      if  copy(SSS_Old, 1 , 5 ) = ' %%%%| '   then
41                         begin
42                         SS: = GPRSIDSTR + SS;
43                         hwndReceiver: = findwindow( ' TFormGPRSServer ' ,nil);  // 向GPRS服务器发送数据
44                             if   hwndReceiver <> 0   then
45                          SendMessageTo(hwndReceiver,SS,ClientInSendToGPRSServer, 0 ,true);
46                          end   else
47                          begin
48                          hwndReceiver: = findwindow( ' TFormServer ' ,nil); // 向无线电服务器发送数据
49                             if   hwndReceiver <> 0   then
50                          SendMessageTo(hwndReceiver,SS,ClientInSendToServerInfo, 0 ,true);
51
52                          end ;
53                     H1:
54           if  G_ShowInfo  then
55                   begin
56                        S: = '' ;
57                         for  j: = 1   to  length(SS) do
58                            begin
59                             S: = S + inttohex(ord(SS [ j ] ), 2 ) + '   ' ;
60                             end ;
61                           memo1.Lines. Add ( ' 通讯服务器<--后台:收到数据! ' + S + # 13 + # 10 );
62                    end ;
63              end ;
64    end ;
65     except
66       on  EConvertError do  begin  Goble_S: = '' ;abort;  end ;
67     end ;
68 end ;

这个里面的36行就是将Java后台发送的数据包解析成GPRSServer模块能够识别的数据包的函数,其实36行是一个接口:IProtocal,我将这个接口设计成了Singleton模式。我将这类解析过程全部封装到了这个接口中。你们只要知道它的作用就可以了,因为里面涉及到商业机密。
   上面的45行和50行就是将已经解析好的数据包按照约定发送给GPRSServer和Server(无线电)模块。
   总体来说整个框架还是比较简单的。
    ClientIn里面一些很“变态”的程序我就不讲了,以免你们对主体程序产生混淆。我在毕业设计文章的时候总是在想,要是再让我写一次这么变态的程序,我还会不会去写。下一章我将会告诉你们为什么我们需要用到转换。

你可能感兴趣的:(Delphi)