繁体   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