delphi - 在 Delphi 中使用 UDP 服务器
问题描述
我有一个使用 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
事件的签名和SendBuffer()
方法都发生了变化。如果您查看新声明,您会很容易看到这一点。
此外,在 Indy 9 和 10 中,您应该使用提供给您的对象的SendTo()
方法将响应发送回发送者,而不是使用服务器集合中 的第一个方法,这可能是也可能不是在多宿主系统中发送的正确套接字。TIdSocketHandle
OnUDPRead
SendBuffer()
TIdUDPServer
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;
推荐阅读
- c++ - 如何理解句子其生命周期始于对 e 的评价
- python - tensorflow“没有足够的内存资源来处理这个命令”。这是什么意思?- Python v3.8
- python - 错误无法以只读模式创建组
- java - 如何根据变量找到id?
- java - Spring Boot 不加载 application.properties
- deep-learning - 尝试将训练数据拟合到 CNN 模型中时出现内存错误
- kubernetes - 此版本的 kubeadm 仅支持部署控制平面版本 >= 1.16.0 的集群。当前版本:v1.12.0 Kubernetes
- c++ - 如何对 2 个数组进行排序,同时保持它们连接到相同的元素?
- excel - 将整数变量更改为非整数值
- python - 如何使用python连接到ec2上的postgresql数据库?