简体   繁体   中英

Using UDP Server with Delphi

I have a project made with Delphi 7. I'm getting an error when I compile with Delphi XE7. The Indy component kit was used in the project. 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. 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. 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.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM