Сообщения, которые вы получаете, имеют структуру - 4-байтовый идентификатор сообщения, за которым следует 4-байтовая строка ASCII, указывающая длину данных сообщения, а затем фактические данные сообщения.
Ваш *Код 1003 * соответствует этой структуре, а ваш код TIdTCPServer
- нет (даже близко!).Во всяком случае, Indy облегчает такую работу, потому что в классе TIdIOHandler
в Indy есть много методов, доступных для чтения любых форматов данных, тогда как TTCPServer
не предлагает ничего, что могло бы вам помочь, вы должны прочитать и проанализировать всевручную.
В этом случае вы можете использовать методы TIdIOHandler.ReadString()
и TIdIOHandler.ReadBytes()
, например:
procedure TForm2.IdTCPServerExecute(AContext: TIdContext);
var
s: string;
l: integer;
Buf: TDataBuf; // TDataBuf = array[0..MAX_DATAPACKET] of byte;
ADispatchPacket: TDispatchPacket;
AQueuedStatus : Boolean;
IdBuf: TIdBytes;
begin
LogQueue.AddToLog(format('TCPServer receiving (onExecute)',[]), llvVerbose);
ZeroMemory(@Buf, MAX_DATAPACKET);
// check if IVD version header is valid for us
s := AContext.Connection.IOHandler.ReadString(4);
if s <> sHeaderID then
raise Exception.CreateFmt('Invalid dispatch packet HeaderID %s', [s]);
Move(ShortString(s)[1], Buf[0], 4);
s := AContext.Connection.IOHandler.ReadString(4);
l := StrToInt(s);
Move(ShortString(s)[1], Buf[4], 4);
AContext.Connection.IOHandler.ReadBytes(IdBuf, l);
Move(PByte(IdBuf)^, Buf[8], l);
// Create the dispatch packet object, move the data to the buffer and queue it.
ADispatchPacket := TDispatchPacket.Create;
try
ADispatchPacket.ReplyTime := MilliSecondOfTheDay(UTCNow);
ADispatchPacket.DataBuf := Buf; // the setter copies the buffer contens
AQueuedStatus := CommandQueue.Enqueue(TOmniMessage.Create(ord(itmDispatchPackage), ADispatchPacket));
except
ADispatchPacket.Free;
raise;
end;
LogQueue.AddToLog(Format('Received package: %d bytes, incoming package was queued = [%s]',[l + HEADER_SIZE, booltostr(AQueuedStatus, True)]), llvVerbose);
AContext.Connection.Disconnect;
end;
procedure TForm2.IdTCPServerException(AContext: TIdContext; AException: Exception);
begin
LogQueue.AddError(format('TcpServer Error: %s',[AException.Message]));
end;
, или вы можете использовать метод TIdIOHandler.ReadStream()
, например:
procedure TForm2.IdTCPServerExecute(AContext: TIdContext);
var
s: ShortString;
l: integer;
Buf: TDataBuf; // TDataBuf = array[0..MAX_DATAPACKET] of byte;
ADispatchPacket: TDispatchPacket;
AQueuedStatus : Boolean;
ABufStream : TIdMemoryBufferStream;
begin
LogQueue.AddToLog(format('TCPServer receiving (onExecute)',[]), llvVerbose);
ZeroMemory(@Buf, MAX_DATAPACKET);
ABufStream := TIdMemoryBufferStream.Create(@Buf, SizeOf(Buf));
try
AContext.Connection.IOHandler.ReadStream(ABufStream, 8, False);
// check if IVD version header is valid for us
s := '0000'; // check if IVD version header is valid for us
Move(Buf[0], s[1], 4);
if s <> sHeaderID then
raise Exception.CreateFmt('Invalid dispatch packet HeaderID %s', [s]);
s := '0000'; // Fetch data package length
Move(Buf[4], s[1], 4);
l := StrToInt(s);
AContext.Connection.IOHandler.ReadStream(ABufStream, l, False);
// Create the dispatch packet object, move the data to the buffer and queue it.
ADispatchPacket := TDispatchPacket.Create;
try
ADispatchPacket.ReplyTime := MilliSecondOfTheDay(UTCNow);
ADispatchPacket.DataBuf := Buf; // the setter copies the buffer contens
AQueuedStatus := CommandQueue.Enqueue(TOmniMessage.Create(ord(itmDispatchPackage), ADispatchPacket));
except
ADispatchPacket.Free;
raise;
end;
finally
ABufStream.Free;
end;
LogQueue.AddToLog(Format('Received package: %d bytes, incoming package was queued = [%s]',[l + HEADER_SIZE, booltostr(AQueuedStatus, True)]), llvVerbose);
AContext.Connection.Disconnect;
end;
procedure TForm2.IdTCPServerException(AContext: TIdContext; AException: Exception);
begin
LogQueue.AddError(format('TcpServer Error: %s',[AException.Message]));
end;
В качестве альтернативы:
procedure TForm2.IdTCPServerExecute(AContext: TIdContext);
var
s: ShortString;
l: integer;
Buf: TDataBuf; // TDataBuf = array[0..MAX_DATAPACKET] of byte;
ADispatchPacket: TDispatchPacket;
AQueuedStatus : Boolean;
ABufStream : TIdMemoryBufferStream;
begin
LogQueue.AddToLog(format('TCPServer receiving (onExecute)',[]), llvVerbose);
ZeroMemory(@Buf, MAX_DATAPACKET);
ABufStream := TIdMemoryBufferStream.Create(@Buf, SizeOf(Buf));
try
AContext.Connection.IOHandler.ReadStream(ABufStream, -1, True);
if ABufStream.Size < 8 then
raise Exception.CreateFmt('Invalid dispatch packet Header size %d', [ABufStream.Size]);
// check if IVD version header is valid for us
s := '0000'; // check if IVD version header is valid for us
Move(Buf[0], s[1], 4);
if s <> sHeaderID then
raise Exception.CreateFmt('Invalid dispatch packet HeaderID %s', [s]);
s := '0000'; // Fetch data package length
Move(Buf[4], s[1], 4);
l := StrToInt(s);
if ABufStream.Size < (l + HEADER_SIZE) then
raise Exception.CreateFmt('Invalid dispatch packet size %d, expected %d', [ABufStream.Size, l + HEADER_SIZE]);
// Create the dispatch packet object, move the data to the buffer and queue it.
ADispatchPacket := TDispatchPacket.Create;
try
ADispatchPacket.ReplyTime := MilliSecondOfTheDay(UTCNow);
ADispatchPacket.DataBuf := Buf; // the setter copies the buffer contens
AQueuedStatus := CommandQueue.Enqueue(TOmniMessage.Create(ord(itmDispatchPackage), ADispatchPacket));
except
ADispatchPacket.Free;
raise;
end;
finally
ABufStream.Free;
end;
LogQueue.AddToLog(Format('Received package: %d bytes, incoming package was queued = [%s]',[l + HEADER_SIZE, booltostr(AQueuedStatus, True)]), llvVerbose);
end;
procedure TForm2.IdTCPServerException(AContext: TIdContext; AException: Exception);
begin
LogQueue.AddError(format('TcpServer Error: %s',[AException.Message]));
end;