简体   繁体   English

在 Delphi 中使用 UDP 服务器

[英]Using UDP Server with Delphi

I have a project made with Delphi 7. I'm getting an error when I compile with Delphi XE7.我有一个用 Delphi 7 制作的项目。当我用 Delphi XE7 编译时出现错误。 The Indy component kit was used in the project.项目中使用了 Indy 组件套件。 I think the problem is due to differences between Indy 9 and Indy 10. I have tried many methods to solve the problem, but I have not been successful.我认为问题是由于 Indy 9 和 Indy 10 之间的差异。我尝试了很多方法来解决问题,但都没有成功。 How can I solve this problem?我怎么解决这个问题?

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;

The parts that give errors:出现错误的部分:

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

In Indy 10, the signature of the OnUDPRead event and the SendBuffer() method have both changed.在 Indy 10 中, OnUDPRead事件的签名和OnUDPRead SendBuffer()方法都发生了变化。 Which you would have easily seen if you looked at the new declarations.如果您查看新声明,您会很容易看到这一点。

Also, in both Indy 9 and 10, you should be sending the response back to the sender using the SendTo() method of the TIdSocketHandle object that OnUDPRead gives you, not the SendBuffer() method of TIdUDPServer , which will use the 1st TIdSocketHandle in the server's Bindings collection, which may or may not be the correct socket to send with.此外,在 Indy 9 和 10 中,您应该使用OnUDPRead为您提供的TIdSocketHandle对象的SendTo()方法将响应发送回发件人,而不是TIdUDPServer SendBuffer()方法,它将使用第一个TIdSocketHandle服务器的Bindings集合,它可能是也可能不是要发送的正确套接字。

Try this instead:试试这个:

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