簡體   English   中英

在 Delphi 中使用 UDP 服務器

[英]Using UDP Server with Delphi

我有一個用 Delphi 7 制作的項目。當我用 Delphi XE7 編譯時出現錯誤。 項目中使用了 Indy 組件套件。 我認為問題是由於 Indy 9 和 Indy 10 之間的差異。我嘗試了很多方法來解決問題,但都沒有成功。 我怎么解決這個問題?

procedure TRealTimeForm.btnListenClick(Sender: TObject);
begin
  try
   FUDPServer.DefaultPort := StrToInt(edtPort.Text);
   FUDPServer.OnUDPRead:=UDPServerUDPRead;
   FUDPServer.Active := True;
   btnListen.Enabled := False;
 except
   on E:Exception do
    ShowMessage(e.Message);
 end;
end;

procedure TRealTimeForm.UDPServerUDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  i: integer;
  lReceiveData: array of Byte;
  sDIN: string;
  year,month,day,hour,minute,second: integer;
  rec: IRecordExt;
  iInt64: Int64;
begin
{
  [0-7]: for check data valid, you can ignore.
[8-23]: these 16 bytes are what you want is the Log entity. The structure is:
Size of structure: 16 bytes
Structure:
//
  UINT64    UserID      //8 bytes
//
  UINT32  Year    :  7;  //7 bits, MAX: 127, base on 2000.
  UINT32  Month  :  4;  //4 bits
  UINT32  Day    :  5;  //5 bits
  UINT32  Action  :  4;    //4 bits
  UINT32  Status  :  5;  //5 bits
  UINT32  JobCode  :  7;  //7 bits, MAX: 127
  UINT32  Antipassback  :1;  //1 bit
  UINT32  DeviceID:  14;  //14 bits, MAX: 16383
  UINT32  Hour  :  5;  //5 bits
  UINT32  Minute  :  6;  //6 bits
  UINT32  Second  :  6;  //6 bits
//
//
[24-31]: device physical address.
}
  try
    if AData.Size < GLogLen then
    begin
      SetLength(lReceiveData,AData.Size);
      AData.ReadBuffer(lReceiveData[0],AData.Size);
      ShowDataLog(lReceiveData);
      Exit;
    end;
    SetLength(lReceiveData,GLogLen);
    AData.ReadBuffer(lReceiveData[0],GLogLen);
    ShowDataLog(lReceiveData);
    if not IsCorectGLog(lReceiveData) then
      Exit;
    rec := CoRecordExt.Create;

    iInt64 := 0;
    for i := 8 to 15 do
    begin
      iInt64 := iInt64 + lReceiveData[i] shl ((i-8) * 8);
    end;
    sDIN := IntToStr(iInt64);
    year := lReceiveData[16] and $7F + 2000;
    month := ((lReceiveData[16] + lReceiveData[17] shl 8) shr 7) and $0F;
    day := (lReceiveData[17] + lReceiveData[18] shl 8) shr 3 and $1F;
    hour := (lReceiveData[21] + lReceiveData[22] shl 8) shr 7 and $1F;
    minute := (lReceiveData[22] + lReceiveData[23] shl 8) shr 4 and $3F;
    second := lReceiveData[23] shr 2 and $3F;

    rec.DIN := sDIN;
    rec.Clock := EncodeDate(year,month,day) + EncodeTime(hour,minute,second,0);
    rec.Verify := (lReceiveData[18] + lReceiveData[19] shl 8) shr 4 and $1F;
    rec.Action := lReceiveData[18] and $0F;
    rec.DN := (lReceiveData[20] + lReceiveData[21] shl 8 + lReceiveData[22] shl 16) shr 1 and $3FFF;
    AddRecord(rec);
    FUDPServer.SendBuffer(ABinding.PeerIP,ABinding.PeerPort,lReceiveData[0],GLogLen);
  except
    on E: Exception do
    begin
      mmoDataLog.Lines.Add(e.Message);
    end;
  end;
end;

出現錯誤的部分:

FUDPServer.OnUDPRead:=UDPServerUDPRead;
FUDPServer.SendBuffer(ABinding.PeerIP,ABinding.PeerPort,lReceiveData[0],GLogLen);

在 Indy 10 中, OnUDPRead事件的簽名和OnUDPRead SendBuffer()方法都發生了變化。 如果您查看新聲明,您會很容易看到這一點。

此外,在 Indy 9 和 10 中,您應該使用OnUDPRead為您提供的TIdSocketHandle對象的SendTo()方法將響應發送回發件人,而不是TIdUDPServer SendBuffer()方法,它將使用第一個TIdSocketHandle服務器的Bindings集合,它可能是也可能不是要發送的正確套接字。

試試這個:

procedure TRealTimeForm.btnListenClick(Sender: TObject);
begin
  try
    FUDPServer.DefaultPort := StrToInt(edtPort.Text);
    FUDPServer.OnUDPRead := UDPServerUDPRead;
    FUDPServer.Active := True;
    btnListen.Enabled := False;
  except
    on E: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TRealTimeForm.UDPServerUDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  i: integer;
  sDIN: string;
  year, month, day, hour, minute, second: Integer;
  rec: IRecordExt;
  iInt64: Int64;
begin
{
  [0-7]: for check data valid, you can ignore.
[8-23]: these 16 bytes are what you want is the Log entity. The structure is:
Size of structure: 16 bytes
Structure:
//
  UINT64    UserID      //8 bytes
//
  UINT32  Year    :  7;  //7 bits, MAX: 127, base on 2000.
  UINT32  Month  :  4;  //4 bits
  UINT32  Day    :  5;  //5 bits
  UINT32  Action  :  4;    //4 bits
  UINT32  Status  :  5;  //5 bits
  UINT32  JobCode  :  7;  //7 bits, MAX: 127
  UINT32  Antipassback  :1;  //1 bit
  UINT32  DeviceID:  14;  //14 bits, MAX: 16383
  UINT32  Hour  :  5;  //5 bits
  UINT32  Minute  :  6;  //6 bits
  UINT32  Second  :  6;  //6 bits
//
//
[24-31]: device physical address.
}
  try
    if Length(AData) < GLogLen then
    begin
      ShowDataLog(AData);
      Exit;
    end;

    ShowDataLog(AData);
    if not IsCorectGLog(AData) then
      Exit;

    rec := CoRecordExt.Create;

    iInt64 := 0;
    for i := 8 to 15 do
    begin
      iInt64 := iInt64 + AData[i] shl ((i-8) * 8);
    end;
    sDIN := IntToStr(iInt64);
    year := AData[16] and $7F + 2000;
    month := ((AData[16] + AData[17] shl 8) shr 7) and $0F;
    day := (AData[17] + AData[18] shl 8) shr 3 and $1F;
    hour := (AData[21] + AData[22] shl 8) shr 7 and $1F;
    minute := (AData[22] + AData[23] shl 8) shr 4 and $3F;
    second := AData[23] shr 2 and $3F;

    rec.DIN := sDIN;
    rec.Clock := EncodeDateTime(year, month, day, hour, minute, second,. 0);
    rec.Verify := (AData[18] + AData[19] shl 8) shr 4 and $1F;
    rec.Action := AData[18] and $0F;
    rec.DN := (AData[20] + AData[21] shl 8 + AData[22] shl 16) shr 1 and $3FFF;
    AddRecord(rec);
    ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, AData, 0, GLogLen);
  except
    on E: Exception do
    begin
      mmoDataLog.Lines.Add(e.Message);
    end;
  end;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM