delphi编写winsocket的流程


delphi编写winsocket的流程
1、在窗体创建的时候启用动态连接库(引用winsock)
   var  aWSAData:TWSAData;
   if WSAStartup($0101,aWSAData)<>0 then
  begin
    MessageBox(Handle,'不能启动winsock动态链接库!','错误',MB_OK);
    Exit;
  end;
2、然后启动监听线程
 Lthread:=TListenthread.CreateIt(9002);
3、线程的构造函数
 constructor CreateIt(port:integer); //创建线程端口//监听线程的构造方法
constructor TlistenThread.CreateIt(port:integer); //创建端口
begin
  inherited create(true);
  lisport:=port;
  FreeOnTerminate:=true;
  resume; //******唤醒线程  重(新)开(始),再继续;恢复;收回;【微软】继续执行 挂起的线程重新执行。
end;
4、线程的销毁函数
destructor  destroy;override;  //结束线程
destructor TlistenThread.destroy;
begin
  if lissocket<>INVALID_SOCKET then
  begin
    //shutdown(lissocket,SD_BOTH);//中断连接,其实连接还存在。
    closesocket(lissocket);   //*********CloseSocket() 是用来关闭一个 Socket 的!
    DebugMessage('Close Socket');
  end;
  inherited destroy;
end;
5、线程的execute方法
procedure Execute; override;  //线程执行过程
procedure TlistenThread.Execute;
var   acceptsocket:Tsocket;
      sa:SOCKADDR_IN;
      salen:integer;
      tempthreadread:ThreadSocketRead;
begin
  { Place thread code here }
  Lissocket:=socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
  //***********************************************************************************
  {socket()系统调用,带有三个参数:
    1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4),
      PF_INET6(IPv6)等
    2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式,
      比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。
    3、参数protocol指定需要使用的协议。虽然可以对同一个协议
      家族(protocol family)(或者说通信域(domain))指定不同的协议
      参数,但是通常只有一个。对于TCP参数可指定为IPPROTO_TCP,对于
      UDP可以用IPPROTO_UDP。你不必显式制定这个参数,使用0则根据前
      两个参数使用默认的协议。}
  //******************************************************************************
  if lissocket=INVALID_SOCKET then
  begin
    DebugMessage('Create Socket Error');
    exit;
  end;
  DebugMessage('Create Socket!');  //调用本单元的 DebugMessage方法   显示成功创建套接字
  sa.sin_family:=PF_INET;
  sa.sin_port:=htons(lisport);
  sa.sin_addr.S_addr:=INADDR_ANY;//---------dcc-----htonl(INADDR_ANY);  //INADDR_ANY,表示本地计算机的默认IP地址
  salen:=sizeof(sa);
  //******************************************************************************
    { sin_family指代协议族,在socket编程中只能是AF_INET ,PF_INET
      sin_port存储端口号(使用网络字节顺序)
      sin_addr存储IP地址,使用in_addr这个数据结构
      s_addr按照网络字节顺序存储IP地址
      sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
    }
   { int bind ( SOCKET s , const struct sockaddr FAR *addr , int namelen );
    [参数]
    s - 指向用Socket函数生成的Socket Descrīptor
    addr - 指向Socket地址的指针
    namelen - 该地址的长度.
    [返回值]
    当函数成功调用时返回0
    调用失败时返回 SOCKET_ERROR
      }
  //***********************************************************************************
  if bind(lissocket,sa,sizeof(sa))=SOCKET_ERROR then
  begin
    closesocket(lissocket);
    DebugMessage('无法打开端口:'+inttostr(lisport));
    exit;
  end;
  DebugMessage('listen on port:'+inttostr(lisport)); //调用本单元的 DebugMessage方法    显示连接的端口号
  listen(lissocket,200);
    //**********************************************
     {socket 套接字,网络编程必用的
      listen ()监听从服务器传来的接收数据
      listen ()创建一个套接口并监听申请的连接.}
    //*******************************************
  while not terminated do
  begin
    acceptsocket:=accept(lissocket,@sa,@salen); //AcceptSocket 是一个阻塞方法,它返回可用来发送和接收数据的 Socket。
    DebugMessage('连接成功!');
    if acceptsocket=INVALID_SOCKET then
    begin
      DebugMessage('接受Socket失败!');
      continue;
    end;
    //调用 UnitSocketRead 方法块中的 ThreadSocketRead.CreateIt 方法 并且同时调用datamoudle的数据库连接控件的连接语句。
    tempthreadread:=ThreadSocketRead.CreateIt(acceptsocket,Datamodule1.ADOConnection1.ConnectionString);
    if tempthreadread<>nil then
    begin
      str:='New thread:'+IntToStr(tempthreadread.threadid);
      synchronize(AddMes);                    //synchronize 时间同步   调用方法本模块的 AddMes方法
    end
    else
    begin
      closesocket(acceptsocket);
      DebugMessage('创建执行线程失败!');   //调用本单元的 DebugMessage方法
    end;

  end;
  closesocket(lissocket);  //一个关闭套接口的方法
end;
 6、实现多线程类
  6.1、类的构造函数
     //类的构造函数
    constructor ThreadSocketRead.CreateIt(S:TSocket;Con:string);
    begin
      CoInitialize( nil ); //使用com对象必须要初始化 主要做Com相关资源的释放,清理  工作...
      inherited Create(true);//继承tthread线程类的构造方法。
  FreeOnTerminate:=True;    //用于结束线程,设置FreeOnTerminate为True ,执行完成线程以后,你不想明确摧毁它。当FreeOnTerminate是假的,线程对象必须明确销毁应用程序代码。
  peerSocket:=S;
  FCon:=con;
  debugList:=Tstringlist.create;
  Suspended:=false;//线程类的一个属性 tthread property Suspended: Boolean read FSuspended write SetSuspended;
end;
  6.2、//定义销毁类方法还没有写完.
destructor ThreadSocketRead.destroy;
begin
  if peerSocket<>INVALID_SOCKET then  closesocket(peerSocket);
  Synchronize(removelist);
  BCSample.Free;
  if FAdoQuery<>nil then FAdoQuery.Free;
  if (Fadoconnection<>nil)then
  begin
     if Fadoconnection.Connected  then  Fadoconnection.Close ;
     Fadoconnection.Free;
  end;

  debugList.Free;
  CoUnInitialize;  //必须使用 主要做Com相关资源的释放,清理工作...
  inherited destroy;
end;
6.3、多线程类的执行
procedure ThreadSocketRead.Execute;
var
  btime:string;
  size:integer;
  timedif,blong1,ErrCode:integer;   //timedif 时差   ErrCode 错误编码, blong1 程序执行时间。
  label endp;
  procedure Writelog;
  begin
     debugList.SaveToFile(BCSample.DebugFileName);
     debugList.clear;
     blong1:=Round((now-strtodatetime(btime))*SecsPerDay);
     Fadoconnection.BeginTrans;
     with Fadoquery do
     begin
       try
         close;
         sql.clear;
         sql.Add('insert into T_FC_CallbackLog (FC_JCPointNo,FC_CBackTime,FC_CBackState,FC_Duration,FC_DataSize,TimeDiff)');
         sql.add('values (:jcno,:btime,:state,:blong,:datasize,:timedif)');
         Parameters.ParamByName('jcno').Value := BCSample.PointNo;
         Parameters.ParamByName('btime').Value := btime;
         Parameters.ParamByName('state').Value := Errcode;
         Parameters.ParamByName('blong').Value := blong1;
         Parameters.ParamByName('dataSize').Value := BCSample.DataSize;
         Parameters.ParamByName('timedif').Value := timedif;
         ExecSql;
         Fadoconnection.CommitTrans;
        Except
          on e:Exception do Fadoconnection.RollbackTrans;
       end;
     end;
   end;
  //将设置ip失败的调查仪信息插入到数据库中
   procedure WriteSetDeviceIPLog;
   begin
     blong1:=Round((now-strtodatetime(btime))*SecsPerDay);
     with Fadoquery do
     begin
       try
         close;
         sql.clear;
         sql.Add('insert into T_FC_SetDeviceIPLog (JCPointNO,TesterNO,CallbackTime,CallbackState,Duration)');
         sql.add('values (:JCPointNO,:TesterNO,:btime,:state,:blong)');
         Parameters.ParamByName('JCPointNO').Value := BCSample.PointNO;
         Parameters.ParamByName('TesterNO').Value := BCSample.DeviceNO;
         Parameters.ParamByName('btime').Value := btime;
         Parameters.ParamByName('state').Value := Errcode;
         Parameters.ParamByName('blong').Value := blong1;
         ExecSql;
        Except
          on e:Exception do exit;
       end;
     end;
   end;
begin
  //这里面紧接着要写对数据包的处理。
  btime:=datetimetostr(now);
  if PeerSocket=INVALID_SOCKET then exit;
  size:=SizeOf(SockAddrIn); //初始化。
  getpeername(PeerSocket,SockAddrIn,size);   //取得对等方的连接。
  PeerIP:=inet_ntoa(SockAddrIn.sin_addr); //inet_ntoa()将网络地址转换成'.'点隔的字符串格式。
  PeerPort:=ntohs(SockAddrIn.sin_port);   //ntohs()将一个无符号短整形数从网络字节顺序转换为主机字节顺序。
  DebugMessage('连接的ip:'+PeerIP+':'+'端口号'+inttostr(PeerPort));//把连接的信息打印出来
  Synchronize(AddTolist);
  //建立数据库的连接。
  try
    Fadoconnection:= Tadoconnection.Create(nil);  //创建数据库连接控件。
    Fadoconnection.ConnectionString:=FCon;        //把连接数据库的字符串赋值。
    Fadoconnection.LoginPrompt:=false;
    Fadoconnection.KeepConnection:=true;
    Fadoconnection.Connected:=true;
  except
    on e:EOleException do
    begin
      DebugMessage('数据库的连接出现问题 :'+e.message);
      exit;
    end;
  end;
  DebugMessage(PeerIP+'Connected to DB');
  FAdoQuery:=TAdoQuery.Create(nil);  //创建查询控件。
  FAdoQuery.Connection:= Fadoconnection;
  //下面将要创建 TBCSample类。
  BCSample:=TBCSample.Create(Fadoconnection);
  BCSample.SetSocket(PeerSocket);                       //进行套结字赋值。
  BCSample.SetDebugList(debugList);
  //
  BCSample.CallTime:=FormatDateTime('YYYY-MM-DD hh:mm:ss',StrtoDateTime(btime)+11/24/60);
  DebugMessage('################'+BCSample.CallTime);
 { if not BCSample.SetIdAndVer then                     //如果设置机器的设备号失败,则进行跳转。
    if not BCSample.SetIdAndVer then  goto endp;
  DebugMessage('设置设备号成功');   }
  ErrCode:=ciReadIdErr;                                 //ciReadIdErr:=1 读ID错。
  if not BCSample.ReadIdAndVer then                     //如果取得不到机器的设备号,则进行跳转。
    if not BCSample.ReadIdAndVer then  goto endp;
  DebugMessage('接受成功,取得设备号'+BCSample.DeviceNO);
  //上面可以接受到数据了
  //取得了设备的编号,从数据库进行查询 取得设备的类型,状态,设备的工作站编号,及回传的id,如果为使用,并得到样本人的编号
  if not BCSample.GetDeviceInfo then
  begin
    DebugMessage('ip:'+PeerIP+' port:'+inttostr(PeerPort)+' DeviceNO:'+BCSample.DeviceNO+' 没有该设备号!' );
    BCSample.Tranfinish(Err_SetupER);    //通讯成功,但连接设备的设置参数有问题。
    goto endp;
  end;
 
  {********设备为使用状态*********}
  if BCSample.OnDeviceStateNo='02' then
  begin
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' DeviceState: 运行');
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 监测点编号:'+BCSample.PointNo);
    Synchronize(UpdateDisply);
    if BCSample.CheckChannelUpdate then
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道信息');
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道FM频点信息清除!');
      ErrCode:=ciClearFMErr;                        // ciClearFMErr=2;          清除FM调频频点出错。
      //******清除设备调频频点信息FM******
      if not BCSample.clearFMValue then
        if not BCSample.clearFMValue then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道FM频点信息清除成功!');

      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道FM频点信息写入!');
      ErrCode:=ciWriteFMValueErr;                         //ciWriteFMValue=3;      //写FM调频频点出错。
      if not BCSample.writeFMValue then
        if not BCSample.writeFMValue then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道FM频点信息写入成功!');

      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道AM频点信息清除!');
      ErrCode:=ciClearAMErr;        //ciClearAMErr=4;                      //清除AM调频频点出错。
      if not BCSample.clearAMValue then
        if not BCSample.clearAMValue then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道AM频点信息清除成功!');

      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道AM频点信息写入!');
      ErrCode:=ciWriteAMValueErr;      //ciWriteAMValue=5;                    //写AM调频频点出错。
      if not BCSample.writeAMValue then
        if not BCSample.writeAMValue then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道AM频点信息写入成功!');
      if not BCSample.UpdateChannelLog then
        if not BCSample.UpdateChannelLog then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 更新指定频道标记成功!');
    end
    else
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道未更改');
    end;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道场强仪时钟!');
    ErrCode:= ciReadDeviceTimeErr;                //ciReadDeviceTimeErr=12;             //读取设备时钟出错
    if not BCSample.ReadDeviceTime then
      if not BCSample.ReadDeviceTime then goto endp;    //取得不了机器时钟,就没有意义,不用再往下进行。
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道场强仪时钟成功!');
    timedif:=round((BCSample.Devicetime - now)*SecsPerDay);          //*******取得时差*********
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 校验指定频道场强仪时钟!');
    ErrCode:=ciWriteDeviceTimeErr;               //ciWriteDeviceTimeErr=6;              //写时钟出错。
    if not  BCSample.WriteDeviceTime then
      if not  BCSample.WriteDeviceTime then goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 校验指定频道场强仪时钟完成!');   //
 
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道溢出标志!');
    ErrCode:=ciGetFlowErr;      //ciGetFlowErr=16;            //读取溢出标志出错
    if not BCSample.recordIsOverFlow then
      if not BCSample.recordIsOverFlow then goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道溢出标志完成!');
    if BCSample.OnisSetTimeSpace = '1' then //指定频道或自动频道的间隔时长有变化。
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 指定频道或自动侦测监测间隔时长有变化!');
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道循环监测间隔时长!');
      ErrCode:=ciwriteWatchValidTimeErr;      //ciwriteWatchValidTimeErr=7;            //写循环监测时长出错
      if not BCSample.writeWatchValidTime then
        if not BCSample.writeWatchValidTime then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道循环监测间隔时长完成!');
      ErrCode:=ciISEQUAlAllChannelSearchIntervalaErr;  //ciISEQUAlAllChannelSearchIntervalaErr:=25
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置自动侦测循环监测间隔时长!');
      ErrCode:=ciwriteAllChannelSearchIntervalaErr;  //ciwriteAllChannelSearchIntervalaErr:=18
      if not BCSample.writeAllChannelSearchIntervala then
        if not BCSample.writeAllChannelSearchIntervala then goto endp;  //如果不能设置自动全频道循环监测间隔时长,则跳转
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置自动侦测循环监测间隔时长成功!');
    end;
{
    100108_ZZF_现在是监测完成自动回传
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道场强仪回传时间!');
    ErrCode:=ciwriteBackTimeErr;                              //ciwriteBackTimeErr:=8;              //写回传时间出错
    if not BCSample.writeBackTime then
      if not BCSample.writeBackTime then  goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道指定频道场强仪回传时间成功!');
}
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道场强仪回传IP地址!');
    ErrCode:=ciSetDeviceIPErr;                    // ciSetDeviceIPErr=9;         //设置ip地址出错
    if not BCSample.SetDeviceIP then
    begin
      if not BCSample.SetDeviceIP then
      begin
        WriteSetDeviceIPLog;     //写设置设备ip错误的日志信息。
        DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道场强仪回传IP地址失败!');
      end
      else
      begin
        DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道场强仪回传IP地址成功!');
      end;
    end
    else
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 设置指定频道场强仪回传IP地址成功!');
    end;

    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道场强仪数据!');
    ErrCode:=ciReadWatchFSRecordErr;               //ciReadWatchFSRecordErr=13;          //读取场强数据出错
    if not BCSample.ReadWatchFSRecord then
      if not BCSample.ReadWatchFSRecord then  goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取指定频道场强仪数据成功!');

    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 清除指定频道场强仪数据!');
    ErrCode:=ciClearWatchFSRecordErr;            //ciClearWatchFSRecordErr=14;         //清除场强仪数据出错
    if not BCSample.ClearWatchFSRecord then
      if not BCSample.ClearWatchFSRecord then goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 清除指定频道场强仪数据成功!');

    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据到文件!');
    ErrCode:=ciSaveFileErr;                                                            //保存文件出错
    if not BCSample.SaveTvdata then
      if not BCSample.SaveTvdata then goto endp;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据到文件成功!');

    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据数据库!');
    try
      if not BCSample.WriteRecordtoDb then
        if not BCSample.WriteRecordtoDb then
          DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据数据库失败!')
        else DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据数据库完成,开始进行自动侦测!')
      else DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 保存指定频道数据数据库完成,开始进行自动侦测!');
    except
      on  e:Exception do DebugMessage(e.Message);
    end;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 开启自动侦测读场强功能');
    ErrCode:=ciautoStartAllChannelSearchErr;  //ciautoStartAllChannelSearchErr:=17
    if BCSample.OnDeviceIsOpen='1' then
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测读场强功能以前已开启');
    end
    else
    begin
      if not BCSample.autoStartAllChannelSearch then  //如果第一次没有开启,在执行一次
        if not BCSample.autoStartAllChannelSearch then goto endp;
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 开启自动侦测读场强功能成功!');
    end;
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取自动侦测循环监测间隔时长!');
    ErrCode:=cireadAllChannelSearchIntervalaErr;  //cireadAllChannelSearchIntervalaErr:=19
    if not BCSample.readAllChannelSearchIntervala then
      if not BCSample.readAllChannelSearchIntervala then  goto endp;   // 读取自动全频道循环监测间隔时长部成功则调转。 //
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取自动侦测循环监测间隔时长成功!间隔:'+inttostr(BCSample.AllChanneljgtime));
 

    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据是否溢出!');
    ErrCode:=cirecordAllChannelIsOverFlowErr;  //cirecordAllChannelIsOverFlowErr:=20
    if  BCSample.recordAllChannelIsOverFlow then
        DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 侦测自动侦测频点数据溢出!')
     else DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 侦测自动侦测频点数据没有溢出!');
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取自动侦测频点数据!');
    ErrCode:=ciReadAllChannelWatchFSRecordErr;  //ciReadAllChannelWatchFSRecordErr:=21
    if not BCSample.ReadAllChannelWatchFSRecord then
      if not BCSample.ReadAllChannelWatchFSRecord then  goto endp; // 读取侦测自动频点数据部成功 ,调转。
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 读取自动侦测频点数据成功!');
    DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+'  自动侦测数据大小: '+inttostr(BCSample.OnAllChannelRevContextSize));
    if BCSample.OnAllChannelRevContextSize>0 then           //如果全频道扫描的流大于零,接受数据后清空
    begin
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 清自动侦测频点数据!  ');
      ErrCode:=ciclearAllChannelSearchRecordErr;  //ciclearAllChannelSearchRecordErr:=22
      if not  BCSample.clearAllChannelSearchRecord then
        if not BCSample.clearAllChannelSearchRecord then  goto endp;  //如果清除不了所有频道监测的的数据,则跳转
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 清自动侦测频点数据成功!');
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到文件!');
      ErrCode:=ciSaveAllChannelTvdataErr;  //ciSaveAllChannelTvdataErr:=23
      if not  BCSample.SaveAllChannelTvdata then
        if not  BCSample.SaveAllChannelTvdata then goto endp; //如果保存不了所有频道监测的的数据到文件,则跳转
      DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到文件成功!');
      try
        DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到数据库!');
        ErrCode:=ciWriteAllChannelRecordtoDbErr;  //ciWriteAllChannelRecordtoDbErr:=24
        if not BCSample.WriteAllChannelRecordtoDb then
          if not BCSample.WriteAllChannelRecordtoDb then
            DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到数据库失败!')
          else  DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到数据库成功!')
        else  DebugMessage(PeerIP+' DeviceNO:'+BCSample.DeviceNO+' 自动侦测频点数据保存到数据库成功!');
      except
        on e:Exception do  DebugMessage(e.Message);
      end;
    end ;

  end;
  ErrCode:=Err_NONE;                        // Err_NONE=100   正确
  endp:
  BCSample.Tranfinish(ErrCode);
  debugList.Add('Errcode: '+inttostr(Errcode));
  debugList.Add('溢出标志: '+BCSample.flag);
  debugList.Add('全频道溢出标志: '+BCSample.flag);
  Writelog;
  //BCSample.destroy;
end;
7、边边角角的信息
//存储信息
procedure ThreadSocketRead.DebugMessage(mes:string);
begin
   if  gdebug then
   begin
     inforStr:=mes;
     synchronize(AddMes1);
   end;
end;
//打印信息到formmain.memo
procedure ThreadSocketRead.AddMes1;
begin
  if gdebug then
    formmain.Memo.Lines.Add(FormatDatetime('hh:mm:ss',Now)+'-*-'+inforStr);
end;
procedure ThreadSocketRead.removelist;
begin
  if not AppExit  and (DeviceItem<>nil) then
  begin
    DeviceItem.Delete;
  end;
end;



原文地址:https://www.cnblogs.com/zhangzhifeng/p/3254537.html