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

📄 utcmppcom.pas

📁 使用delphi编写的cmpp接口程序源代码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
          Result := ICP_ERR_SUBMITERR;
        end;
      wrError:
        begin
          Result := ICP_ERR_SUBMITERR;
        end;
    end;

    //删除对象
    csWaitMsg.Enter;
    WaitList.Remove(MsgWait);
    csWaitMsg.Leave;

    if Result = 0 then
    begin
      //返回消息处理

      tmpMsgID := MsgWait.MsgID;
      tmpMsgID := ntohll(tmpMsgID);

      tmpMsgIDStr :=
        IntToHex(tmpMsgID and $000000000000FFFF, 4) +                           //序列号
      IntToHex((tmpMsgID and $0000003FFFFF0000) shr 16, 6) +                    //短信网关代码

      IntToHex((tmpMsgID and $F000000000000000) shr 60, 2) +                    //月份的二进制表示
      IntToHex((tmpMsgID and $0F80000000000000) shr 55, 2) +                    //日的二进制表示
      IntToHex((tmpMsgID and $007C000000000000) shr 50, 2) +                    //小时的二进制表示
      IntToHex((tmpMsgID and $0003F00000000000) shr 44, 2) +                    //分的二进制表示
      IntToHex((tmpMsgID and $00000FC000000000) shr 38, 2);                     //秒的二进制表示

      StrPLCopy(Pchar(@pSubmitInfo^.sMsgID), tmpMsgIDStr, 21);

      Result := MsgWait.Status;
    end
    else
    begin
      //如果没有返回则有可能是没有发出去,此时要删除队列

      csSendMsg.Enter;

      if SendList.Remove(pMsg) <> -1 then
        Dispose(pMsg);

      csSendMsg.Leave;

    end;

    //s释放对象

    MsgWait.Free;

  except

  end;

end;

function TCMPPService.CMPPMsg_SeTCMPPMsgHeadEx(pMsg: PCMPPMsgHead; MsgCode, MsgLen,
  SwquenceID: Integer): integer;
begin

  Result := MsgLen + sizeof(TCMPPMsgHead);
  pMsg.PacketLength := htonl(Result);
  pMsg.Command_Id := htonl(MsgCode);
  pMsg.SwquenceID := htonl(SwquenceID);

end;

procedure TCMPPService.ClearList;
var
  i                                     : integer;
  MsgWait                               : TCMPPMsgWait;
  pMsg                                  : PCMPPDeliverResp;
begin
  //清理发送队列
  csWaitMsg.Enter;

  SysLog.LogInfo('Clear WaitList Count= ' + IntToStr(WaitList.Count));
  if WaitList.Count > 0 then
    for i := WaitList.Count - 1 to 0 do
    begin
      MsgWait := WaitList[i];
      MsgWait.WaitEvent.SetEvent;
    end;

  csWaitMsg.Leave;

  // 清理接收队列
  csRecMsg.Enter;

  SysLog.LogInfo('Clear RecQueue Count= ' + IntToStr(RecQueue.Count));
  if RecQueue.Count > 0 then
    for i := RecQueue.Count - 1 to 0 do
    begin
      //取消息
      pMsg := PCMPPDeliverResp(RecQueue.Pop);

      //释放内存
      Dispose(pMsg);
    end;
  csRecMsg.Leave;

  SysLog.LogInfo('Clear End');
end;

procedure TCMPPService.SetWaitMsg(ASwquenceID: integer; Status: Integer; MsgID: Int64);
var
  TmpWait                               : TCMPPMsgWait;
  i                                     : integer;
begin
  csWaitMsg.Enter;
  for i := 0 to WaitList.Count - 1 do
  begin
    TmpWait := WaitList[i];

    if TmpWait.FSwquenceID = ASwquenceID then
    begin
      TmpWait.Status := Status;

      TmpWait.MsgID := MsgID;

      TmpWait.WaitEvent.SetEvent;
    end;
  end;
  csWaitMsg.Leave;

end;

procedure TCMPPService.Execute;
var
  Msg                                   : tagMSG;

begin
  inherited;

  InitSys;

  while not (Terminated) and GetMessage(Msg, 0, 0, 0) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;

  UnInitSys;
end;

procedure TCMPPService.InitSys;
begin
  InitParam;

  SetServiceStatus(SS_IDLE);

  //事件
  ServiceEvent := TEvent.Create(nil, False, False, '');

  //队列
  csSendMsg := TCriticalSection.Create;
  SendEvent := TEvent.Create(nil, False, False, '');
  csWaitMsg := TCriticalSection.Create;
  RecEvent := TEvent.Create(nil, False, False, '');
  csRecMsg := TCriticalSection.Create;
  SendList := TList.Create;
  WaitList := TList.Create;
  RecQueue := TQueue.Create;

  //定时器
  ReConTimer := TTimer.Create(nil);
  ReConTimer.Enabled := False;
  ReConTimer.OnTimer := ReConTimerDo;

  ActiveTimer := TTimer.Create(nil);
  ActiveTimer.Interval := 20000;
  ActiveTimer.Enabled := True;
  ActiveTimer.OnTimer := ActiveTimerDo;

  //Socket
  CMPPClient := TClientSocket.Create(nil);
  csSocket := TCriticalSection.Create;

  MsgSend := TCMPPMsgSendThread.Create(Self);

  with CMPPClient do
  begin
    Active := False;
    Address := ServiceIP;
    Port := ServicePort;
    ClientType := ctNonBlocking;

    //分配事件处理代码
    OnConnect := CMPP_ConnectSuc;
    OnDisconnect := CMPP_DisConnect;
    OnError := CMPP_Error;
    OnWrite := CMPP_CanWrite;
    OnRead := CMPP_Read;
  end;

  ClientSeqID := 0;

  bServiceActive := False;
  bComCanWrite := False;
  bComReboot := False;

end;

procedure TCMPPService.UnInitSys;
begin
  Stop;

  MsgSend.Resume;
  MsgSend.Terminate;

  CMPPClient.Free;
  csSocket.Free;
  ReConTimer.Free;
  ActiveTimer.Free;

  SendList.Free;
  WaitList.Free;
  RecQueue.Free;
  csSendMsg.Free;
  csWaitMsg.Free;
  csRecMsg.Free;
  SendEvent.Free;
  RecEvent.Free;

  ServiceEvent.Free;
end;

procedure TCMPPService.ActiveTimerDo(Sender: TObject);
begin

  if bServiceActive and bComCanWrite then
    CMPPMsg_SendActive;

end;

function TCMPPService.CMPPMsg_SendActive: integer;

var
  Len                                   : integer;
  PMsg                                  : PChar;
begin
  { DONE : 发送Exit消息 }
  //组合消息
  Len := CMPPMsg_SeTCMPPMsgHead(@CMPPMsg_Active, CMD_ACTIVE, 0);

  //发送消息
  PMsg := @CMPPMsg_Active;
  Result := CMPPMsg_Send(PMsg^, Len);
end;

function TCMPPService.AddSubmitMsgEx(pSubmitInfo: PCMPPSubmit): integer;

var
  pMsg                                  : PCMPPMsg_Submit;
  pMsgSub                               : PCMPPMsgBody_Submit_Sub;
  Len                                   : Integer;
  SwquenceID                            : Integer;
  MsgWait                               : TCMPPMsgWait;
  UserNum                               : integer;
  UserTel                               : TStrings;

  tmpMsgID                              : integer;
  tmpMsgIDStr                           : string;
begin
  //如果服务没有启动,则返回

  try

    if not bServiceActive then
    begin
      Result := ICP_ERR_NOLOGIN;
      exit;
    end;

    //如果socket在 重新连接,则返回
    if bComReboot then
    begin
      Result := ICP_ERR_CONTRETRY;
      exit;
    end;
    //如果发送窗口满了,则返回
    if (WaitList.Count + SendList.Count) >= RequestWindow * 1.5 then
    begin
      Result := ICP_ERR_SUBMITOUTOFWINDOW;
      exit;
    end;

    //组合消息
    new(pMsg);
    ZeroMemory(pMsg, sizeof(TCMPPMsg_Submit));
    with pMsg.Body, pSubmitInfo^ do
    begin
      Msg_Id := 0;
      Pk_total := byPKTotal;
      Pk_number := byPKNumber;
      Registered_Delivery := byneedReport;
      Msg_level := byMsglevel;

      StrLCopy(@Service_Id, @sServiceID, 10);
      Fee_UserType := byFeeUserType;
      StrLCopy(@Fee_terminal_Id, @sFeeAddr, 20);
      Fee_terminal_type := bychargTermidType;
      TP_pId := byPID;
      TP_udhi := byUDHI;
      Msg_Fmt := byMsg_Fmt;
      StrLCopy(@Msg_src, @sSPID, 6);
      StrLCopy(@FeeType, @sFeeType, 2);
      StrLCopy(@FeeCode, @sFeeCode, 6);
      StrLCopy(@ValId_Time, @sSchedule, 17);
      StrLCopy(@At_Time, @sExpire, 17);
      StrLCopy(@Src_Id, @sOrgAddr, 20);

      UserTel := TStringList.Create;
      try
        UserTel.Delimiter := ';';
        UserTel.DelimitedText := StrPas(@sDestAddrs);

        DestUsr_tl := UserTel.Count;

        if DestUsr_tl > 100 then
          DestUsr_tl := 100;

        for UserNum := 0 to DestUsr_tl - 1 do
        begin
          StrLCopy(Pchar(Integer(@Dest_terminal_Id) + UserNum * 32), PChar(UserTel[UserNum]), 32);
        end
      finally
        UserTel.Free;
      end;

      pMsgSub := PCMPPMsgBody_Submit_Sub((Pchar(@Dest_terminal_Id) + DestUsr_tl * 32));
      pMsgSub^.Dest_terminal_type := byDestTerminalType;
      pMsgSub^.Msg_Length := byUDLen;
      if pMsgSub^.Msg_Length > 160 then
        pMsgSub^.Msg_Length := 160;

      StrLCopy(@pMsgSub^.Msg_Content, @sUserData, pMsgSub^.Msg_Length);
      StrLCopy(Pchar(Integer(@pMsgSub^.Msg_Content) + pMsgSub^.Msg_Length), @sLinkID, 20);

      Len := sizeof(TCMPPMsgBody_SubmitHead) + DestUsr_tl * 32 + 22 +
        pMsgSub^.Msg_Length;
    end;

    CMPPMsg_SeTCMPPMsgHead(@(pMsg^.Head), CMD_SUBMIT, Len);
    SwquenceID := ntohl(pMsg.Head.SwquenceID);

    //添加到队列
    csSendMsg.Enter;
    SendList.Add(pMsg);

    //激活等待发送线程
    if MsgSend.Suspended then
    begin
      MsgSend.Suspended := False;
    end;
    csSendMsg.Leave;

    //在等待队列中等待返回 sMsgID, nErrorCode,

    { DONE : 在等待队列中等待返回 sMsgID, nErrorCode, }

    //创建等待对象,
    MsgWait := TCMPPMsgWait.Create(SwquenceID);
    csWaitMsg.Enter;
    WaitList.Add(MsgWait);
    csWaitMsg.Leave;

    //等待返回消息
    case MsgWait.WaitEvent.WaitFor(3000) of                                     //
      wrSignaled:
        begin
          //结果赋值
          Result := 0;
        end;
      wrTimeout:
        begin
          Result := ICP_ERR_SUBMITTIMEOUT;
        end;
      wrAbandoned:
        begin
          Result := ICP_ERR_SUBMITERR;
        end;
      wrError:
        begin
          Result := ICP_ERR_SUBMITERR;
        end;
    end;

    //删除对象
    csWaitMsg.Enter;
    WaitList.Remove(MsgWait);
    csWaitMsg.Leave;

    if Result = 0 then
    begin
      //返回消息处理

      tmpMsgID := MsgWait.MsgID;
      tmpMsgID := ntohll(tmpMsgID);

      tmpMsgIDStr :=
        IntToHex(tmpMsgID and $000000000000FFFF, 4) +                           //序列号
      IntToHex((tmpMsgID and $0000003FFFFF0000) shr 16, 6) +                    //短信网关代码

      IntToHex((tmpMsgID and $F000000000000000) shr 60, 2) +                    //月份的二进制表示
      IntToHex((tmpMsgID and $0F80000000000000) shr 55, 2) +                    //日的二进制表示
      IntToHex((tmpMsgID and $007C000000000000) shr 50, 2) +                    //小时的二进制表示
      IntToHex((tmpMsgID and $0003F00000000000) shr 44, 2) +                    //分的二进制表示
      IntToHex((tmpMsgID and $00000FC000000000) shr 38, 2);                     //秒的二进制表示

      StrPLCopy(Pchar(@pSubmitInfo^.sMsgID), tmpMsgIDStr, 21);

      Result := MsgWait.Status;
    end
    else
    begin
      //如果没有返回则有可能是没有发出去,此时要删除队列

      csSendMsg.Enter;

      if SendList.Remove(pMsg) <> -1 then
        Dispose(pMsg);

      csSendMsg.Leave;

    end;

    //s释放对象

    MsgWait.Free;

  except

  end;
end;

{ TCMPPMsgSendThread }

constructor TCMPPMsgSendThread.Create(AService: TCMPPService);
begin
  inherited Create(True);
  FService := AService;
  FreeOnTerminate := True;

  SysLog.LogInfo('Thread Create');

end;

destructor TCMPPMsgSendThread.Destroy;
begin

  inherited;
end;

procedure TCMPPMsgSendThread.Execute;
var
  PMsg                                  : PCMPPMsg_Submit;
  bHadMsg                               : Boolean;
  i                                     : Integer;
begin
  inherited;
  //未设置停止标志前一直运行
  //FService.bComCanWrite               FService.bComReboot  FService.bServiceActive
    //     FService.SendList.Count    FService.SendList[0]

  while not (Terminated) do
  begin
    //从队列中获取数据然后发送

    with FService do
    begin
      if bServiceActive and bComCanWrite and not bComReboot and (WaitList.Count
        < RequestWindow) then
      begin
        //验证是否有消息需要发送 ,如果没有等待
        if (SendList.Count = 0) and not Self.Suspended then
        begin
          Self.Suspended := True;
        end;

        { if SendList.Count = 0 then
         begin
           case SendEvent.WaitFor(2000) of                                       //
             wrSignaled:
               begin
                 bHadMsg := True;
               end;
             wrTimeout:
               begin
                 bHadMsg := False;
               end;
             wrAbandoned:
               begin
                 bHadMsg := False;
               end;
             wrError:
               begin
                 bHadMsg := False;
               end;
           end;
         end
         else
         begin
           bHadMsg := True;
         end;    }

        csSendMsg.Enter;
        if                                                                      //bHadMsg and
        (SendList.Count > 0) then
        begin
          //取消息

          for i := SendList.Count - 1 downto 0 do
          begin
            PMsg := PCMPPMsg_Submit(SendList[i]);
            SendList.Delete(i);

            //发送
            if CMPPMsg_Send(PMsg^, ntohl(pmsg^.Head.PacketLength)) = -1 then
            begin
              SysLog.LogInfo('发送数据出错!');
            end
            else
            begin

              //SysLog.LogInfo('发送消息成功!Seq=');
              //SysLog.LogInfo(PMsg, ntohl(pmsg^.Head.PacketLength));
            end;

            //发送完释放内存
            Dispose(PMsg);

          end;
        end;
        csSendMsg.Leave;
      end
      else
      begin
        // 如果暂时不能发送,则休息
        Sleep(300);
      end;
    end;
  end;

end;

{ TCMPPMsgWait }

constructor TCMPPMsgWait.Create;
begin
  WaitEvent := TEvent.Create(nil, False, False, '');

  FSwquenceID := ASwquenceID;
end;

destructor TCMPPMsgWait.Destroy;
begin
  WaitEvent.Free;
  inherited;
end;

end.

⌨️ 快捷键说明

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