I am working with Indy10 in Delphi XE4, and am trying to make a simple TCP connection with a TCP server on the network. The server sends a simple Hello World message, and then disconnects, and waits for another connection. I have the following code, to connect, and to try and read the message from the server.
with Client do
begin
Host := '10.10.81.122';
Port := 3490;
Connect;
if IOHandler.Connected then
writeln('Connected!');
if IOHandler.InputBufferIsEmpty then
begin
if IOHandler.CheckForDataOnSource(1000) then
begin
writeln('Buffer size:' + IntToStr(IOHandler.RecvBufferSize));
IOhandler.ReadBytes(buffer, IOHandler.RecvBufferSize);
end
else
writeln('Message not received');
end;
end;
When I run this code, I get a value for the recvBufferSize, but the buffer remains empty and then I get a connection terminated gracefully message.
The RecvBufferSize
has nothing to do with how many data is actually available for reading. The RecvBufferSize
merely specifies the size that Indy uses when allocating internal buffers for reading raw data from the socket. Whatever raw data is actually read gets placed in the IOHandler.InputBuffer
for later use by ReadBytes()
and other IOHandler
reading methods.
Use this code instead:
with Client do
begin
Host := '10.10.81.122';
Port := 3490;
try
Connect;
WriteLn('Connected!');
if IOHandler.CheckForDataOnSource(1000) then
begin
WriteLn(Bytes available:' + IntToStr(IOHandler.InputBuffer.Size));
IOHandler.ReadBytes(buffer, IOHandler.InputBuffer.Size);
end else
WriteLn('Message not received');
except
on E: Exception do
WriteLn('Error! ' + E.Message);
end;
end;
Alternatively:
with Client do
begin
Host := '10.10.81.122';
Port := 3490;
ReadTimeout := 1000;
try
Connect;
WriteLn('Connected!');
IOHandler.ReadBytes(buffer, -1);
if Length(buffer) > 0 then
WriteLn('Bytes read:' + IntToStr(Length(buffer)))
else
WriteLn('Message not received');
except
on E: Exception do
WriteLn('Error! ' + E.Message);
end;
end;
That being said, that is no guaratee that you will actually receive the full message, since this code is merely reading whatever raw data is available at the moment of reading. Since your server is sending a line break at the end of the data, you can use ReadLn()
instead of ReadBytes()
and let Indy wait until the line break is actually received:
with Client do
begin
Host := '10.10.81.122';
Port := 3490;
ReadTimeout := 1000;
try
Connect;
WriteLn('Connected!');
Msg := IOHandler.ReadLn;
if not IOHandler.ReadLnTimedOut then
WriteLn('Message read:' + Msg)
else
WriteLn('Message not received');
except
on E: Exception do
WriteLn('Error! ' + E.Message);
end;
end;
Alternatively:
with Client do
begin
Host := '10.10.81.122';
Port := 3490;
try
Connect;
WriteLn('Connected!');
Msg := IOHandler.ReadLn(LF, 1000);
if not IOHandler.ReadLnTimedOut then
WriteLn('Message read:' + Msg)
else
WriteLn('Message not received');
except
on E: Exception do
WriteLn('Error! ' + E.Message);
end;
end;